Beispiel #1
0
int IsAbsoluteFileName(const char *f)
{
    int off = 0;

// Check for quoted strings

    for (off = 0; f[off] == '\"'; off++)
    {
    }

#ifdef _WIN32
    if (IsFileSep(f[off]) && IsFileSep(f[off + 1]))
    {
        return true;
    }

    if (isalpha(f[off]) && f[off + 1] == ':' && IsFileSep(f[off + 2]))
    {
        return true;
    }
#endif
    if (f[off] == '/')
    {
        return true;
    }

    return false;
}
Beispiel #2
0
int CompressPath(char *dest, const char *src)
{
    char node[CF_BUFSIZE];
    int nodelen;
    int rootlen;

    memset(dest, 0, CF_BUFSIZE);

    rootlen = RootDirLength(src);
    strncpy(dest, src, rootlen);

    for (const char *sp = src + rootlen; *sp != '\0'; sp++)
    {
        if (IsFileSep(*sp))
        {
            continue;
        }

        for (nodelen = 0; (sp[nodelen] != '\0') && (!IsFileSep(sp[nodelen])); nodelen++)
        {
            if (nodelen > CF_MAXLINKSIZE)
            {
                Log(LOG_LEVEL_ERR, "Link in path suspiciously large");
                return false;
            }
        }

        strncpy(node, sp, nodelen);
        node[nodelen] = '\0';

        sp += nodelen - 1;

        if (strcmp(node, ".") == 0)
        {
            continue;
        }

        if (strcmp(node, "..") == 0)
        {
            if (!ChopLastNode(dest))
            {
                Log(LOG_LEVEL_DEBUG, "used .. beyond top of filesystem!");
                return false;
            }

            continue;
        }
        else
        {
            AddSlash(dest);
        }

        if (!JoinPath(dest, node))
        {
            return false;
        }
    }

    return true;
}
Beispiel #3
0
char *MapNameCopy(const char *s)
{
    Writer *w = StringWriter();

    /* c:\a\b -> /cygdrive/c\a\b */
    if (s[0] && isalpha(s[0]) && s[1] == ':')
    {
        WriterWriteF(w, "/cygdrive/%c", s[0]);
        s += 2;
    }

    for (; *s; s++)
    {
        /* a//b//c -> a/b/c */
        /* a\\b\\c -> a\b\c */
        if (IsFileSep(*s) && IsFileSep(*(s + 1)))
        {
            continue;
        }

        /* a\b\c -> a/b/c */
        WriterWriteChar(w, *s == '\\' ? '/' : *s);
    }

    return StringWriterClose(w);
}
Beispiel #4
0
void DeleteRedundantSlashes(char *str)
{
    int move_from;
    // Invariant: newpos <= oldpos
    int oldpos = RootDirLength(str);
    int newpos = oldpos;
    while (str[oldpos] != '\0')
    {
        // Skip over subsequent separators.
        while (IsFileSep(str[oldpos]))
        {
            oldpos++;
        }
        move_from = oldpos;

        // And then skip over the next path component.
        while (str[oldpos] != '\0' && !IsFileSep(str[oldpos]))
        {
            oldpos++;
        }

        // If next character is file separator, move past it, since we want to keep one.
        if (IsFileSep(str[oldpos]))
        {
            oldpos++;
        }

        int move_len = oldpos - move_from;
        memmove(&str[newpos], &str[move_from], move_len);
        newpos += move_len;
    }

    str[newpos] = '\0';
}
Beispiel #5
0
int RootDirLength(char *f)

  /* Return length of Initial directory in path - */

{
#ifdef NT
  int len;

if (IsFileSep(f[0]) && IsFileSep(f[1]))
   {
   /* UNC style path */

   /* Skip over host name */
   for (len=2; !IsFileSep(f[len]); len++)
      {
      if (f[len] == '\0')
         {
         return len;
         }
      }
   
   /* Skip over share name */
   for (len++; !IsFileSep(f[len]); len++)
      {
      if (f[len] == '\0')
         {
         return len;
         }
      }
   
   /* Skip over file separator */
   len++;
   
   return len;
   }
 if ( isalpha(f[0]) && f[1] == ':' && IsFileSep(f[2]) )
    {
    return 3;
    }
#endif
 if (*f == '/')
    {
    return 1;
    }
 
 return 0;
}
Beispiel #6
0
static int NTRootDirLength(const char *f)
{
    int len;

    if (IsFileSep(f[0]) && IsFileSep(f[1]))
    {
        /* UNC style path */

        /* Skip over host name */
        for (len = 2; !IsFileSep(f[len]); len++)
        {
            if (f[len] == '\0')
            {
                return len;
            }
        }

        /* Skip over share name */

        for (len++; !IsFileSep(f[len]); len++)
        {
            if (f[len] == '\0')
            {
                return len;
            }
        }

        /* Skip over file separator */
        len++;

        return len;
    }

    if (isalpha(f[0]) && f[1] == ':')
    {
        if (IsFileSep(f[2]))
        {
            return 3;
        }

        return 2;
    }

    return UnixRootDirLength(f);
}
Beispiel #7
0
static int UnixRootDirLength(const char *f)
{
    if (IsFileSep(*f))
    {
        return 1;
    }

    return 0;
}
Beispiel #8
0
int IsAbsPath(const char *path)
{
    if (IsFileSep(*path))
    {
        return true;
    }
    else
    {
        return false;
    }
}
Beispiel #9
0
int IsAbsoluteFileName(char *f)

{
#ifdef NT
if (IsFileSep(f[0]) && IsFileSep(f[1]))
   {
   return true;
   }
if ( isalpha(f[0]) && f[1] == ':' && IsFileSep(f[2]) )
   {
   return true;
   }
#endif
if (*f == '/')
   {
   return true;
   }

return false;
}
Beispiel #10
0
void AddSlash(char *str)
{
    char *sp, *sep = FILE_SEPARATOR_STR;
    int f = false, b = false;

    if (str == NULL)
    {
        return;
    }

// add root slash on Unix systems
    if (strlen(str) == 0)
    {
#if !defined(_WIN32)
        strcpy(str, "/");
#endif
        return;
    }

    /* Try to see what convention is being used for filenames
       in case this is a cross-system copy from Win/Unix */

    for (sp = str; *sp != '\0'; sp++)
    {
        switch (*sp)
        {
        case '/':
            f = true;
            break;
        case '\\':
            b = true;
            break;
        default:
            break;
        }
    }

    if (f && (!b))
    {
        sep = "/";
    }
    else if (b && (!f))
    {
        sep = "\\";
    }

    if (!IsFileSep(str[strlen(str) - 1]))
    {
        strcat(str, sep);
    }
}
Beispiel #11
0
// Can remove several slashes if they are redundant.
void DeleteSlash(char *str)
{
    int size = strlen(str);
    if ((size == 0) || (str == NULL))
    {
        return;
    }

    int root = RootDirLength(str);
    while (IsFileSep(str[size - 1]) && size - 1 > root)
    {
        size--;
    }
    str[size] = '\0'; /* no-op if we didn't change size */
}
Beispiel #12
0
void DeleteSlash(char *str)
{
    if ((strlen(str) == 0) || (str == NULL))
    {
        return;
    }

    if (strcmp(str, "/") == 0)
    {
        return;
    }

    if (IsFileSep(str[strlen(str) - 1]))
    {
        str[strlen(str) - 1] = '\0';
    }
}
Beispiel #13
0
const char *FirstFileSeparator(const char *str)
{
    assert(str);
    assert(strlen(str) > 0);

    if(strncmp(str, "\\\\", 2) == 0)  // windows share
    {
        return str + 1;
    }

    for(const char *pos = str; *pos != '\0'; pos++)
    {
        if(IsFileSep(*pos))
        {
            return pos;
        }
    }

    return NULL;
}
Beispiel #14
0
const char *LastFileSeparator(const char *str)
  /* Return pointer to last file separator in string, or NULL if 
     string does not contains any file separtors */
{
    const char *sp;

/* Walk through string backwards */

    sp = str + strlen(str) - 1;

    while (sp >= str)
    {
        if (IsFileSep(*sp))
        {
            return sp;
        }
        sp--;
    }

    return NULL;
}
Beispiel #15
0
int CompressPath(char *dest,char *src)

{ char *sp;
  char node[CF_BUFSIZE];
  int nodelen;
  int rootlen;

Debug2("CompressPath(%s,%s)\n",dest,src);

memset(dest,0,CF_BUFSIZE);

rootlen = RootDirLength(src);
strncpy(dest,src,rootlen);
 
for (sp = src+rootlen; *sp != '\0'; sp++)
   {
   if (IsFileSep(*sp))
      {
      continue;
      }

   for (nodelen = 0; sp[nodelen] != '\0' && !IsFileSep(sp[nodelen]); nodelen++)
      {
      if (nodelen > CF_MAXLINKSIZE)
         {
         CfLog(cferror,"Link in path suspiciously large","");
         return false;
         }
      }

   strncpy(node, sp, nodelen);
   node[nodelen] = '\0';
   
   sp += nodelen - 1;
   
   if (strcmp(node,".") == 0)
      {
      continue;
      }
   
   if (strcmp(node,"..") == 0)
      {
      if (!ChopLastNode(dest))
         {
         Debug("cfengine: used .. beyond top of filesystem!\n");
         return false;
         }
   
      continue;
      }
   else
      {
      AddSlash(dest);
      }

   if (BufferOverflow(dest,node))
      {
      return false;
      }
   
   strcat(dest,node);
   }
 
return true;
}
Beispiel #16
0
/**
 * @TODO fix the dangerous path lengths
 */
int CompressPath(char *dest, const char *src)
{
    char node[CF_BUFSIZE];
    int nodelen;
    int rootlen;

    memset(dest, 0, CF_BUFSIZE);

    rootlen = RootDirLength(src);
    memcpy(dest, src, rootlen);

    for (const char *sp = src + rootlen; *sp != '\0'; sp++)
    {
        if (IsFileSep(*sp))
        {
            continue;
        }

        for (nodelen = 0; (sp[nodelen] != '\0') && (!IsFileSep(sp[nodelen])); nodelen++)
        {
            if (nodelen > CF_MAXLINKSIZE)
            {
                Log(LOG_LEVEL_ERR, "Link in path suspiciously large");
                return false;
            }
        }

        strncpy(node, sp, nodelen);
        node[nodelen] = '\0';

        sp += nodelen - 1;

        if (strcmp(node, ".") == 0)
        {
            continue;
        }

        if (strcmp(node, "..") == 0)
        {
            if (!ChopLastNode(dest))
            {
                Log(LOG_LEVEL_DEBUG, "used .. beyond top of filesystem!");
                return false;
            }

            continue;
        }

        AddSlash(dest);

        /* TODO use dest_size parameter instead of CF_BUFSIZE. */
        size_t ret = strlcat(dest, node, CF_BUFSIZE);

        if (ret >= CF_BUFSIZE)
        {
            Log(LOG_LEVEL_ERR,
                "Internal limit reached in CompressPath(),"
                " path too long: '%s' + '%s'",
                dest, node);
            return false;
        }
    }

    return true;
}
Beispiel #17
0
PromiseResult VerifyRelativeLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp)
{
    char *sp, *commonto, *commonfrom;
    char buff[CF_BUFSIZE], linkto[CF_BUFSIZE];
    int levels = 0;

    if (*source == '.')
    {
        return VerifyLink(ctx, destination, source, attr, pp);
    }

    if (!CompressPath(linkto, sizeof(linkto), source))
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link '%s' to '%s'", destination, source);
        return PROMISE_RESULT_INTERRUPTED;
    }

    commonto = linkto;
    commonfrom = destination;

    if (strcmp(commonto, commonfrom) == 0)
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link '%s' to '%s', can't link file '%s' to itself",
             destination, source, commonto);
        return PROMISE_RESULT_INTERRUPTED;
    }

    while (*commonto == *commonfrom)
    {
        commonto++;
        commonfrom++;
    }

    while (!((IsAbsoluteFileName(commonto)) && (IsAbsoluteFileName(commonfrom))))
    {
        commonto--;
        commonfrom--;
    }

    commonto++;

    for (sp = commonfrom; *sp != '\0'; sp++)
    {
        if (IsFileSep(*sp))
        {
            levels++;
        }
    }

    memset(buff, 0, CF_BUFSIZE);

    strcat(buff, ".");
    strcat(buff, FILE_SEPARATOR_STR);

    while (--levels > 0)
    {
        const char add[] = ".." FILE_SEPARATOR_STR;

        if (!PathAppend(buff, sizeof(buff), add, FILE_SEPARATOR))
        {
            Log(LOG_LEVEL_ERR,
                "Internal limit reached in VerifyRelativeLink(),"
                " path too long: '%s' + '%s'",
                buff, add);
            return PROMISE_RESULT_FAIL;
        }
    }

    if (!PathAppend(buff, sizeof(buff), commonto, FILE_SEPARATOR))
    {
        Log(LOG_LEVEL_ERR,
            "Internal limit reached in VerifyRelativeLink() end,"
            " path too long: '%s' + '%s'",
            buff, commonto);
        return PROMISE_RESULT_FAIL;
    }

    return VerifyLink(ctx, destination, buff, attr, pp);
}
Beispiel #18
0
bool MakeParentDirectory(const char *parentandchild, bool force)
{
    char *spc, *sp;
    char currentpath[CF_BUFSIZE];
    char pathbuf[CF_BUFSIZE];
    struct stat statbuf;
    mode_t mask;
    int rootlen;
    char Path_File_Separator;

#ifdef __APPLE__
/* Keeps track of if dealing w. resource fork */
    int rsrcfork;

    rsrcfork = 0;

    char *tmpstr;
#endif

    Log(LOG_LEVEL_DEBUG, "Trying to create a parent directory for '%s%s'", parentandchild, force ? " (force applied)" : "");

    if (!IsAbsoluteFileName(parentandchild))
    {
        Log(LOG_LEVEL_ERR, "Will not create directories for a relative filename '%s'. Has no invariant meaning",
              parentandchild);
        return false;
    }

    strncpy(pathbuf, parentandchild, CF_BUFSIZE - 1);   /* local copy */

#ifdef __APPLE__
    if (strstr(pathbuf, _PATH_RSRCFORKSPEC) != NULL)
    {
        rsrcfork = 1;
    }
#endif

/* skip link name */
/* This cast is necessary, as  you can't have (char* -> char*)
   and (const char* -> const char*) functions in C */
    sp = (char *) LastFileSeparator(pathbuf);

    if (sp == NULL)
    {
        sp = pathbuf;
    }
    *sp = '\0';

    DeleteSlash(pathbuf);

    if (lstat(pathbuf, &statbuf) != -1)
    {
        if (S_ISLNK(statbuf.st_mode))
        {
            Log(LOG_LEVEL_VERBOSE, "INFO: %s is a symbolic link, not a true directory!", pathbuf);
        }

        if (force)              /* force in-the-way directories aside */
        {
            struct stat dir;

            stat(pathbuf, &dir);

            if (!S_ISDIR(dir.st_mode))  /* if the dir exists - no problem */
            {
                struct stat sbuf;

                if (DONTDO)
                {
                    return true;
                }

                strcpy(currentpath, pathbuf);
                DeleteSlash(currentpath);
                strcat(currentpath, ".cf-moved");
                Log(LOG_LEVEL_INFO, "Moving obstructing file/link %s to %s to make directory", pathbuf, currentpath);

                /* If cfagent, remove an obstructing backup object */

                if (lstat(currentpath, &sbuf) != -1)
                {
                    if (S_ISDIR(sbuf.st_mode))
                    {
                        DeleteDirectoryTree(currentpath);
                    }
                    else
                    {
                        if (unlink(currentpath) == -1)
                        {
                            Log(LOG_LEVEL_INFO, "Couldn't remove file/link '%s' while trying to remove a backup. (unlink: %s)",
                                  currentpath, GetErrorStr());
                        }
                    }
                }

                /* And then move the current object out of the way... */

                if (rename(pathbuf, currentpath) == -1)
                {
                    Log(LOG_LEVEL_INFO, "Warning: The object '%s' is not a directory. (rename: %s)", pathbuf, GetErrorStr());
                    return false;
                }
            }
        }
        else
        {
            if (!S_ISLNK(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode))
            {
                Log(LOG_LEVEL_INFO,
                      "The object %s is not a directory. Cannot make a new directory without deleting it.", pathbuf);
                return false;
            }
        }
    }

/* Now we can make a new directory .. */

    currentpath[0] = '\0';

    rootlen = RootDirLength(parentandchild);
    strncpy(currentpath, parentandchild, rootlen);

    for (sp = (char*) parentandchild + rootlen, spc = currentpath + rootlen; *sp != '\0'; sp++)
    {
        if (!IsFileSep(*sp) && *sp != '\0')
        {
            *spc = *sp;
            spc++;
        }
        else
        {
            Path_File_Separator = *sp;
            *spc = '\0';

            if (strlen(currentpath) == 0)
            {
            }
            else if (stat(currentpath, &statbuf) == -1)
            {
                if (!DONTDO)
                {
                    mask = umask(0);

                    if (mkdir(currentpath, DEFAULTMODE) == -1)
                    {
                        Log(LOG_LEVEL_ERR, "Unable to make directories to '%s'. (mkdir: %s)", parentandchild, GetErrorStr());
                        umask(mask);
                        return false;
                    }
                    umask(mask);
                }
            }
            else
            {
                if (!S_ISDIR(statbuf.st_mode))
                {
#ifdef __APPLE__
                    /* Ck if rsrc fork */
                    if (rsrcfork)
                    {
                        tmpstr = xmalloc(CF_BUFSIZE);
                        strncpy(tmpstr, currentpath, CF_BUFSIZE);
                        strncat(tmpstr, _PATH_FORKSPECIFIER, CF_BUFSIZE);

                        /* CFEngine removed terminating slashes */
                        DeleteSlash(tmpstr);

                        if (strncmp(tmpstr, pathbuf, CF_BUFSIZE) == 0)
                        {
                            free(tmpstr);
                            return true;
                        }
                        free(tmpstr);
                    }
#endif

                    Log(LOG_LEVEL_ERR, "Cannot make %s - %s is not a directory! (use forcedirs=true)", pathbuf,
                          currentpath);
                    return false;
                }
            }

            /* *spc = FILE_SEPARATOR; */
            *spc = Path_File_Separator;
            spc++;
        }
    }

    Log(LOG_LEVEL_DEBUG, "Directory for '%s' exists. Okay", parentandchild);
    return true;
}
Beispiel #19
0
int MakeDirectoriesFor(char *file,char force)  /* Make all directories which underpin file */

{ char *sp,*spc;
  char currentpath[CF_BUFSIZE];
  char pathbuf[CF_BUFSIZE];
  struct stat statbuf;
  mode_t mask;
  int rootlen;
  char Path_File_Separator;
    
#ifdef DARWIN
/* Keeps track of if dealing w. resource fork */
int rsrcfork;
rsrcfork = 0;

char * tmpstr;
#endif    
    
if (!IsAbsoluteFileName(file))
   {
   snprintf(OUTPUT,CF_BUFSIZE*2,"Will not create directories for a relative filename (%s). Has no invariant meaning\n",file);
   CfLog(cferror,OUTPUT,"");
   return false;
   }

strncpy(pathbuf,file,CF_BUFSIZE-1);                                      /* local copy */


#ifdef DARWIN
/* Dealing w. a rsrc fork? */
if (strstr(pathbuf, _PATH_RSRCFORKSPEC) != NULL)
   {
   rsrcfork = 1;
   }
#endif

/* skip link name */
 sp = LastFileSeparator(pathbuf);
 if (sp == NULL)
    {
    sp = pathbuf;
    }
 *sp = '\0';
 
 DeleteSlash(pathbuf); 
 
 if (lstat(pathbuf,&statbuf) != -1)
    {
    if (S_ISLNK(statbuf.st_mode))
       {
       Verbose("%s: INFO: %s is a symbolic link, not a true directory!\n",VPREFIX,pathbuf);
       }
    
    if (force == 'y')   /* force in-the-way directories aside */
       {
       if (!S_ISDIR(statbuf.st_mode))  /* if the dir exists - no problem */
          {
          if (ISCFENGINE)
             {
             struct Tidy tp;
             struct TidyPattern tpat;
             struct stat sbuf;

             if (DONTDO)
                {
                return true;
                }
             
             strcpy(currentpath,pathbuf);
             DeleteSlash(currentpath);
             strcat(currentpath,".cf-moved");
             snprintf(OUTPUT,CF_BUFSIZE,"Moving obstructing file/link %s to %s to make directory",pathbuf,currentpath);
             CfLog(cferror,OUTPUT,"");
             
             /* If cfagent, remove an obstructing backup object */
             
             if (lstat(currentpath,&sbuf) != -1)
                {
                if (S_ISDIR(sbuf.st_mode))
                   {
                   tp.maxrecurse = 2;
                   tp.tidylist = &tpat;
                   tp.next = NULL;
                   tp.path = currentpath;
                   
                   tpat.recurse = CF_INF_RECURSE;
                   tpat.age = 0;
                   tpat.size = 0;
                   tpat.pattern = strdup("*");
                   tpat.classes = strdup("any");
                   tpat.defines = NULL;
                   tpat.elsedef = NULL;
                   tpat.dirlinks = 'y';
                   tpat.travlinks = 'n';
                   tpat.rmdirs = 'y';
                   tpat.searchtype = 'a';
                   tpat.log = 'd';
                   tpat.inform = 'd';
                   tpat.next = NULL;
//                   RecursiveTidySpecialArea(currentpath,&tp,CF_INF_RECURSE,&sbuf);
                   free(tpat.pattern);
                   free(tpat.classes);
                   
                   if (rmdir(currentpath) == -1)
                      {
                      snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove directory %s while trying to remove a backup\n",currentpath);
                      CfLog(cfinform,OUTPUT,"rmdir");
                      }
                   }
                else
                   {
                   if (unlink(currentpath) == -1)
                      {
                      snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove file/link %s while trying to remove a backup\n",currentpath);
                      CfLog(cfinform,OUTPUT,"rmdir");
                      }
                   }
                }
             
             /* And then move the current object out of the way...*/
             
             if (rename(pathbuf,currentpath) == -1)
                {
                snprintf(OUTPUT,CF_BUFSIZE*2,"Warning. The object %s is not a directory.\n",pathbuf);
                CfLog(cfinform,OUTPUT,"");
                CfLog(cfinform,"Could not make a new directory or move the block","rename");
                return(false);
                }
             }
          }
       else
          {
          if (! S_ISLNK(statbuf.st_mode) && ! S_ISDIR(statbuf.st_mode))
             {
             snprintf(OUTPUT,CF_BUFSIZE*2,"Warning. The object %s is not a directory.\n",pathbuf);
             CfLog(cfinform,OUTPUT,"");
             CfLog(cfinform,"Cannot make a new directory without deleting it!\n\n","");
             return(false);
             }
          }
       }
    }
 
/* Now we can make a new directory .. */ 
 
 currentpath[0] = '\0';
 
 rootlen = RootDirLength(sp);
 strncpy(currentpath, file, rootlen);

 for (sp = file+rootlen, spc = currentpath+rootlen; *sp != '\0'; sp++)
    {
    if (!IsFileSep(*sp) && *sp != '\0')
       {
       *spc = *sp;
       spc++;
       }
    else
       {
       Path_File_Separator = *sp;
       *spc = '\0';
       
       if (strlen(currentpath) == 0)
          {
          }
       else if (stat(currentpath,&statbuf) == -1)
          {
          Debug2("cfengine: Making directory %s, mode %o\n",currentpath,DEFAULTMODE);
          
          if (! DONTDO)
             {
             mask = umask(0);
             
             if (mkdir(currentpath,DEFAULTMODE) == -1)
                {
                snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to make directories to %s\n",file);
                CfLog(cferror,OUTPUT,"mkdir");
                umask(mask);
                return(false);
                }
             umask(mask);
             }
          }
       else
          {
          if (! S_ISDIR(statbuf.st_mode))
             {
#ifdef DARWIN
             /* Ck if rsrc fork */
             if (rsrcfork)
                {
                tmpstr = malloc(CF_BUFSIZE);
                strncpy(tmpstr, currentpath, CF_BUFSIZE);
                strncat(tmpstr, _PATH_FORKSPECIFIER, CF_BUFSIZE);
                
                /* Cfengine removed terminating slashes */
                DeleteSlash(tmpstr);
                
                if (strncmp(tmpstr, pathbuf, CF_BUFSIZE) == 0)
                   {
                   free(tmpstr);
                   return(true);
                   }
                free(tmpstr);
                }
#endif
             
             snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot make %s - %s is not a directory! (use forcedirs=true)\n",pathbuf,currentpath);
             CfLog(cferror,OUTPUT,"");
             return(false);
             }
          }
       
       /* *spc = FILE_SEPARATOR; */
       *spc = Path_File_Separator;
       spc++;
       }
    }
 
 Debug("Directory for %s exists. Okay\n",file);
 return(true);
}
Beispiel #20
0
PromiseResult VerifyRelativeLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp)
{
    char *sp, *commonto, *commonfrom;
    char buff[CF_BUFSIZE], linkto[CF_BUFSIZE], add[CF_BUFSIZE];
    int levels = 0;

    if (*source == '.')
    {
        return VerifyLink(ctx, destination, source, attr, pp);
    }

    if (!CompressPath(linkto, source))
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link %s to %s\n", destination, source);
        return PROMISE_RESULT_FAIL;
    }

    commonto = linkto;
    commonfrom = destination;

    if (strcmp(commonto, commonfrom) == 0)
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link %s to %s - can't link file %s to itself\n",
             destination, source, commonto);
        return PROMISE_RESULT_FAIL;
    }

    while (*commonto == *commonfrom)
    {
        commonto++;
        commonfrom++;
    }

    while (!((IsAbsoluteFileName(commonto)) && (IsAbsoluteFileName(commonfrom))))
    {
        commonto--;
        commonfrom--;
    }

    commonto++;

    for (sp = commonfrom; *sp != '\0'; sp++)
    {
        if (IsFileSep(*sp))
        {
            levels++;
        }
    }

    memset(buff, 0, CF_BUFSIZE);

    strcat(buff, ".");
    strcat(buff, FILE_SEPARATOR_STR);

    while (--levels > 0)
    {
        snprintf(add, CF_BUFSIZE - 1, "..%c", FILE_SEPARATOR);

        if (!JoinPath(buff, add))
        {
            return PROMISE_RESULT_FAIL;
        }
    }

    if (!JoinPath(buff, commonto))
    {
        return PROMISE_RESULT_FAIL;
    }

    return VerifyLink(ctx, destination, buff, attr, pp);
}
Beispiel #21
0
bool MakeParentDirectory(const char *parentandchild, bool force)
{
    char *sp;
    char currentpath[CF_BUFSIZE];
    char pathbuf[CF_BUFSIZE];
    struct stat statbuf;
    mode_t mask;
    int rootlen;

#ifdef __APPLE__
/* Keeps track of if dealing w. resource fork */
    int rsrcfork;

    rsrcfork = 0;

    char *tmpstr;
#endif

    Log(LOG_LEVEL_DEBUG, "Trying to create a parent directory%s for: %s",
        force ? " (force applied)" : "",
        parentandchild);

    if (!IsAbsoluteFileName(parentandchild))
    {
        Log(LOG_LEVEL_ERR,
            "Will not create directories for a relative filename: %s",
            parentandchild);
        return false;
    }

    strlcpy(pathbuf, parentandchild, CF_BUFSIZE);   /* local copy */

#ifdef __APPLE__
    if (strstr(pathbuf, _PATH_RSRCFORKSPEC) != NULL)
    {
        rsrcfork = 1;
    }
#endif

/* skip link name */

    sp = (char *) LastFileSeparator(pathbuf);                /* de-constify */

    if (sp == NULL)
    {
        sp = pathbuf;
    }
    *sp = '\0';

    DeleteSlash(pathbuf);

    if (lstat(pathbuf, &statbuf) != -1)
    {
        if (S_ISLNK(statbuf.st_mode))
        {
            Log(LOG_LEVEL_VERBOSE, "'%s' is a symbolic link, not a directory",
                pathbuf);
        }

        if (force)              /* force in-the-way directories aside */
        {
            struct stat dir;
            stat(pathbuf, &dir);

            /* If the target directory exists as a directory, no problem. */
            /* If the target directory exists but is not a directory, then
             * rename it to ".cf-moved": */
            if (!S_ISDIR(dir.st_mode))
            {
                struct stat sbuf;

                if (DONTDO)
                {
                    return true;
                }

                strcpy(currentpath, pathbuf);
                DeleteSlash(currentpath);
                /* TODO overflow check! */
                strlcat(currentpath, ".cf-moved", sizeof(currentpath));
                Log(LOG_LEVEL_INFO,
                    "Moving obstructing file/link %s to %s to make directory",
                    pathbuf, currentpath);

                /* Remove possibly pre-existing ".cf-moved" backup object. */
                if (lstat(currentpath, &sbuf) != -1)
                {
                    if (S_ISDIR(sbuf.st_mode))                 /* directory */
                    {
                        DeleteDirectoryTree(currentpath);
                    }
                    else                                 /* not a directory */
                    {
                        if (unlink(currentpath) == -1)
                        {
                            Log(LOG_LEVEL_INFO, "Couldn't remove file/link"
                                " '%s' while trying to remove a backup"
                                " (unlink: %s)",
                                currentpath, GetErrorStr());
                        }
                    }
                }

                /* And then rename the current object to ".cf-moved". */
                if (rename(pathbuf, currentpath) == -1)
                {
                    Log(LOG_LEVEL_INFO,
                        "Couldn't rename '%s' to .cf-moved"
                        " (rename: %s)", pathbuf, GetErrorStr());
                    return false;
                }
            }
        }
        else
        {
            if (!S_ISLNK(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode))
            {
                Log(LOG_LEVEL_INFO, "The object '%s' is not a directory."
                    " Cannot make a new directory without deleting it.",
                    pathbuf);
                return false;
            }
        }
    }

/* Now we make directories descending from the root folder down to the leaf */

    currentpath[0] = '\0';

    rootlen = RootDirLength(parentandchild);
    /* currentpath is not NULL terminated on purpose! */
    strncpy(currentpath, parentandchild, rootlen);

    for (size_t z = rootlen; parentandchild[z] != '\0'; z++)
    {
        const char c = parentandchild[z];

        /* Copy up to the next separator. */
        if (!IsFileSep(c))
        {
            currentpath[z] = c;
            continue;
        }

        const char path_file_separator = c;
        currentpath[z]                 = '\0';

        /* currentpath is complete path for each of the parent directories.  */

        if (currentpath[0] == '\0')
        {
            /* We are at dir "/" of an absolute path, no need to create. */
        }
        /* WARNING: on Windows stat() fails if path has a trailing slash! */
        else if (stat(currentpath, &statbuf) == -1)
        {
            if (!DONTDO)
            {
                mask = umask(0);

                if (mkdir(currentpath, DEFAULTMODE) == -1)
                {
                    Log(LOG_LEVEL_ERR,
                        "Unable to make directory: %s (mkdir: %s)",
                        currentpath, GetErrorStr());
                    umask(mask);
                    return false;
                }
                umask(mask);
            }
        }
        else
        {
            if (!S_ISDIR(statbuf.st_mode))
            {
#ifdef __APPLE__
                /* Ck if rsrc fork */
                if (rsrcfork)
                {
                    tmpstr = xmalloc(CF_BUFSIZE);
                    strlcpy(tmpstr, currentpath, CF_BUFSIZE);
                    strncat(tmpstr, _PATH_FORKSPECIFIER, CF_BUFSIZE);

                    /* CFEngine removed terminating slashes */
                    DeleteSlash(tmpstr);

                    if (strncmp(tmpstr, pathbuf, CF_BUFSIZE) == 0)
                    {
                        free(tmpstr);
                        return true;
                    }
                    free(tmpstr);
                }
#endif

                Log(LOG_LEVEL_ERR,
                    "Cannot make %s - %s is not a directory!"
                    " (use forcedirs=true)", pathbuf, currentpath);
                return false;
            }
        }

        currentpath[z] = path_file_separator;
    }

    Log(LOG_LEVEL_DEBUG, "Directory for '%s' exists. Okay", parentandchild);
    return true;
}