예제 #1
0
파일: server_common.c 프로젝트: fabix/core
int CfSecOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *dirname)
{
    Dir *dirh;
    const struct dirent *dirp;
    int offset, cipherlen;
    char out[CF_BUFSIZE];

    if (!IsAbsoluteFileName(dirname))
    {
        sprintf(sendbuffer, "BAD: request to access a non-absolute filename\n");
        cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1);
        SendTransaction(&conn->conn_info, out, cipherlen, CF_DONE);
        return -1;
    }

    if ((dirh = DirOpen(dirname)) == NULL)
    {
        Log(LOG_LEVEL_VERBOSE, "Couldn't open dir %s", dirname);
        snprintf(sendbuffer, CF_BUFSIZE, "BAD: cfengine, couldn't open dir %s\n", dirname);
        cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1);
        SendTransaction(&conn->conn_info, out, cipherlen, CF_DONE);
        return -1;
    }

/* Pack names for transmission */

    memset(sendbuffer, 0, CF_BUFSIZE);

    offset = 0;

    for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh))
    {
        if (strlen(dirp->d_name) + 1 + offset >= CF_BUFSIZE - CF_MAXLINKSIZE)
        {
            cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, offset + 1);
            SendTransaction(&conn->conn_info, out, cipherlen, CF_MORE);
            offset = 0;
            memset(sendbuffer, 0, CF_BUFSIZE);
            memset(out, 0, CF_BUFSIZE);
        }

        strncpy(sendbuffer + offset, dirp->d_name, CF_MAXLINKSIZE);
        /* + zero byte separator */
        offset += strlen(dirp->d_name) + 1;
    }

    strcpy(sendbuffer + offset, CFD_TERMINATOR);

    cipherlen =
        EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, offset + 2 + strlen(CFD_TERMINATOR));
    SendTransaction(&conn->conn_info, out, cipherlen, CF_DONE);
    DirClose(dirh);
    return 0;
}
예제 #2
0
파일: files_links.c 프로젝트: baptr/core
static char *AbsLinkPath(const char *from, const char *relto)
/* Take an abolute source and a relative destination object
   and find the absolute name of the to object */
{
    int pop = 1;
    static char destination[CF_BUFSIZE];

    if (IsAbsoluteFileName(relto))
    {
        ProgrammingError("Call to AbsLInkPath with absolute pathname");
    }

    strcpy(destination, from);  /* reuse to save stack space */

    const char *sp = NULL;
    for (sp = relto; *sp != '\0'; sp++)
    {
        if (strncmp(sp, "../", 3) == 0)
        {
            pop++;
            sp += 2;
            continue;
        }

        if (strncmp(sp, "./", 2) == 0)
        {
            sp += 1;
            continue;
        }

        break;                  /* real link */
    }

    while (pop > 0)
    {
        ChopLastNode(destination);
        pop--;
    }

    if (strlen(destination) == 0)
    {
        strcpy(destination, "/");
    }
    else
    {
        AddSlash(destination);
    }

    strcat(destination, sp);
    Log(LOG_LEVEL_DEBUG, "Reconstructed absolute linkname '%s'", destination);
    return destination;
}
예제 #3
0
bool KillGhostLink(EvalContext *ctx, const char *name, Attributes attr, const Promise *pp,
                   PromiseResult *result)
{
    char linkbuf[CF_BUFSIZE], tmp[CF_BUFSIZE];
    char linkpath[CF_BUFSIZE], *sp;
    struct stat statbuf;

    memset(linkbuf, 0, CF_BUFSIZE);
    memset(linkpath, 0, CF_BUFSIZE);

    if (readlink(name, linkbuf, CF_BUFSIZE - 1) == -1)
    {
        Log(LOG_LEVEL_VERBOSE, "Can't read link '%s' while checking for deadlinks", name);
        return true;            /* ignore */
    }

    if (!IsAbsoluteFileName(linkbuf))
    {
        strcpy(linkpath, name); /* Get path to link */

        for (sp = linkpath + strlen(linkpath); (*sp != FILE_SEPARATOR) && (sp >= linkpath); sp--)
        {
            *sp = '\0';
        }
    }

    strcat(linkpath, linkbuf);
    CompressPath(tmp, sizeof(tmp), linkpath);

    if (stat(tmp, &statbuf) == -1)    /* link points nowhere */
    {
        if ((attr.link.when_no_file == cfa_delete) || (attr.recursion.rmdeadlinks))
        {
            Log(LOG_LEVEL_VERBOSE, "'%s' is a link which points to '%s', but that file doesn't seem to exist", name,
                  linkbuf);

            if (!DONTDO)
            {
                unlink(name);   /* May not work on a client-mounted system ! */
                cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr,
                     "Removing ghost '%s', reference to something that is not there", name);
                *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE);
                return true;
            }
        }
    }

    return false;
}
예제 #4
0
EditContext *NewEditContext(EvalContext *ctx, char *filename, Attributes a, const Promise *pp)
{
    EditContext *ec;

    if (!IsAbsoluteFileName(filename))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Relative file name %s was marked for editing but has no invariant meaning\n", filename);
        return NULL;
    }

    ec = xcalloc(1, sizeof(EditContext));

    ec->filename = filename;
    ec->empty_first = a.edits.empty_before_use;

    if (a.haveeditline)
    {
        if (!LoadFileAsItemList(ctx, &(ec->file_start), filename, a, pp))
        {
        free(ec);
        return NULL;
        }
    }

    if (a.haveeditxml)
    {
#ifdef HAVE_LIBXML2
        if (!LoadFileAsXmlDoc(ctx, &(ec->xmldoc), filename, a, pp))
        {
            free(ec);
            return NULL;
        }
#else
        cfPS(ctx, OUTPUT_LEVEL_ERROR, CF_FAIL, "", pp, a, " !! Cannot edit XML files without LIBXML2\n");
        free(ec);
        return NULL;
#endif
    }

    if (a.edits.empty_before_use)
    {
        CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Build file model from a blank slate (emptying)\n");
        DeleteItemList(ec->file_start);
        ec->file_start = NULL;
    }

    EDIT_MODEL = true;
    return ec;
}
예제 #5
0
파일: files_names.c 프로젝트: npe9/core
FilePathType FilePathGetType(const char *file_path)
{
    if (IsAbsoluteFileName(file_path))
    {
        return FILE_PATH_TYPE_ABSOLUTE;
    }
    else if (*file_path == '.')
    {
        return FILE_PATH_TYPE_RELATIVE;
    }
    else
    {
        return FILE_PATH_TYPE_NON_ANCHORED;
    }
}
예제 #6
0
파일: files_names.c 프로젝트: patuchov/core
FilePathType FilePathGetType(const char *file_path)
{
    if (IsAbsoluteFileName(file_path))
    {
        return FILE_PATH_TYPE_ABSOLUTE;
    }
    else if (IsFileOutsideDefaultRepository(file_path))
    {
        return FILE_PATH_TYPE_RELATIVE;
    }
    else
    {
        return FILE_PATH_TYPE_NON_ANCHORED;
    }
}
예제 #7
0
파일: server_common.c 프로젝트: fabix/core
int CfOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *oldDirname)
{
    Dir *dirh;
    const struct dirent *dirp;
    int offset;
    char dirname[CF_BUFSIZE];

    TranslatePath(dirname, oldDirname);

    if (!IsAbsoluteFileName(dirname))
    {
        sprintf(sendbuffer, "BAD: request to access a non-absolute filename\n");
        SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE);
        return -1;
    }

    if ((dirh = DirOpen(dirname)) == NULL)
    {
        Log(LOG_LEVEL_DEBUG, "Couldn't open dir '%s'", dirname);
        snprintf(sendbuffer, CF_BUFSIZE, "BAD: cfengine, couldn't open dir %s\n", dirname);
        SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE);
        return -1;
    }

/* Pack names for transmission */

    memset(sendbuffer, 0, CF_BUFSIZE);

    offset = 0;

    for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh))
    {
        if (strlen(dirp->d_name) + 1 + offset >= CF_BUFSIZE - CF_MAXLINKSIZE)
        {
            SendTransaction(&conn->conn_info, sendbuffer, offset + 1, CF_MORE);
            offset = 0;
            memset(sendbuffer, 0, CF_BUFSIZE);
        }

        strncpy(sendbuffer + offset, dirp->d_name, CF_MAXLINKSIZE);
        offset += strlen(dirp->d_name) + 1;     /* + zero byte separator */
    }

    strcpy(sendbuffer + offset, CFD_TERMINATOR);
    SendTransaction(&conn->conn_info, sendbuffer, offset + 2 + strlen(CFD_TERMINATOR), CF_DONE);
    DirClose(dirh);
    return 0;
}
예제 #8
0
파일: files_edit.c 프로젝트: nperron/core
EditContext *NewEditContext(char *filename, Attributes a)
{
    EditContext *ec;

    if (!IsAbsoluteFileName(filename))
    {
        Log(LOG_LEVEL_ERR, "Relative file name '%s' was marked for editing but has no invariant meaning", filename);
        return NULL;
    }

    ec = xcalloc(1, sizeof(EditContext));

    ec->filename = filename;

    if (a.haveeditline)
    {
        if (!LoadFileAsItemList(&(ec->file_start), filename, a.edits))
        {
        free(ec);
        return NULL;
        }
    }

    if (a.haveeditxml)
    {
#ifdef HAVE_LIBXML2
        if (!LoadFileAsXmlDoc(&(ec->xmldoc), filename, a.edits))
        {
            free(ec);
            return NULL;
        }
#else
        Log(LOG_LEVEL_ERR, "Cannot edit XML files without LIBXML2");
        free(ec);
        return NULL;
#endif
    }

    if (a.edits.empty_before_use)
    {
        Log(LOG_LEVEL_VERBOSE, "Build file model from a blank slate (emptying)");
        DeleteItemList(ec->file_start);
        ec->file_start = NULL;
    }

    return ec;
}
예제 #9
0
파일: files_names.c 프로젝트: npe9/core
bool ChopLastNode(char *str)
  /* Chop off trailing node name (possible blank) starting from
     last character and removing up to the first / encountered 
     e.g. /a/b/c -> /a/b
     /a/b/ -> /a/b
     Will also collapse redundant/repeating path separators.
  */
{
    char *sp;
    int ret;

    DeleteRedundantSlashes(str);

/* Here cast is necessary and harmless, str is modifiable */
    if ((sp = (char *) LastFileSeparator(str)) == NULL)
    {
        int pos = RootDirLength(str);
        if (str[pos] == '\0')
        {
            ret = false;
        }
        else
        {
            str[pos] = '.';
            str[pos + 1] = '\0';
            ret = true;
        }
    }
    else
    {
        // Don't chop the root slash in an absolute path.
        if (IsAbsoluteFileName(str) && FirstFileSeparator(str) == sp)
        {
            *(++sp) = '\0';
        }
        else
        {
            *sp = '\0';
        }
        ret = true;
    }

    return ret;
}
예제 #10
0
파일: files_links.c 프로젝트: baptr/core
int ExpandLinks(char *dest, const char *from, int level)
{
    char buff[CF_BUFSIZE];
    char node[CF_MAXLINKSIZE];
    struct stat statbuf;
    int lastnode = false;

    memset(dest, 0, CF_BUFSIZE);

    if (level >= CF_MAXLINKLEVEL)
    {
        Log(LOG_LEVEL_ERR, "Too many levels of symbolic links to evaluate absolute path");
        return false;
    }

    const char *sp = from;

    while (*sp != '\0')
    {
        if (*sp == FILE_SEPARATOR)
        {
            sp++;
            continue;
        }

        sscanf(sp, "%[^/]", node);
        sp += strlen(node);

        if (*sp == '\0')
        {
            lastnode = true;
        }

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

        if (strcmp(node, "..") == 0)
        {
            continue;
        }
        else
        {
            strcat(dest, "/");
        }

        strcat(dest, node);

        if (lstat(dest, &statbuf) == -1)        /* File doesn't exist so we can stop here */
        {
            Log(LOG_LEVEL_ERR, "Can't stat '%s' in ExpandLinks. (lstat: %s)", dest, GetErrorStr());
            return false;
        }

        if (S_ISLNK(statbuf.st_mode))
        {
            memset(buff, 0, CF_BUFSIZE);

            if (readlink(dest, buff, CF_BUFSIZE - 1) == -1)
            {
                Log(LOG_LEVEL_ERR, "Expand links can't stat '%s'. (readlink: %s)", dest, GetErrorStr());
                return false;
            }
            else
            {
                if (buff[0] == '.')
                {
                    ChopLastNode(dest);

                    AddSlash(dest);

                    if (!JoinPath(dest, buff))
                    {
                        return false;
                    }
                }
                else if (IsAbsoluteFileName(buff))
                {
                    strcpy(dest, buff);
                    DeleteSlash(dest);

                    if (strcmp(dest, from) == 0)
                    {
                        Log(LOG_LEVEL_DEBUG, "No links to be expanded");
                        return true;
                    }

                    if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1)))
                    {
                        return false;
                    }
                }
                else
                {
                    ChopLastNode(dest);
                    AddSlash(dest);
                    strcat(dest, buff);
                    DeleteSlash(dest);

                    if (strcmp(dest, from) == 0)
                    {
                        Log(LOG_LEVEL_DEBUG, "No links to be expanded");
                        return true;
                    }

                    memset(buff, 0, CF_BUFSIZE);

                    if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1)))
                    {
                        return false;
                    }
                }
            }
        }
    }

    return true;
}
예제 #11
0
파일: files_links.c 프로젝트: baptr/core
PromiseResult VerifyHardLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp)
{
    char to[CF_BUFSIZE], absto[CF_BUFSIZE];
    struct stat ssb, dsb;

    memset(to, 0, CF_BUFSIZE);

    if ((!IsAbsoluteFileName(source)) && (*source != '.'))        /* links without a directory reference */
    {
        snprintf(to, CF_BUFSIZE - 1, ".%c%s", FILE_SEPARATOR, source);
    }
    else
    {
        strncpy(to, source, CF_BUFSIZE - 1);
    }

    if (!IsAbsoluteFileName(to))        /* relative path, must still check if exists */
    {
        Log(LOG_LEVEL_DEBUG, "Relative link destination detected '%s'", to);
        strcpy(absto, AbsLinkPath(destination, to));
        Log(LOG_LEVEL_DEBUG, "Absolute path to relative link '%s', destination '%s'", absto, destination);
    }
    else
    {
        strcpy(absto, to);
    }

    if (stat(absto, &ssb) == -1)
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, attr, "Source file %s doesn't exist\n", source);
        return PROMISE_RESULT_WARN;
    }

    if (!S_ISREG(ssb.st_mode))
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, attr,
             "Source file %s is not a regular file, not appropriate to hard-link\n", to);
        return PROMISE_RESULT_WARN;
    }

    Log(LOG_LEVEL_DEBUG, "Trying to hard link '%s' -> '%s'", destination, to);

    if (stat(destination, &dsb) == -1)
    {
        return MakeHardLink(ctx, destination, to, attr, pp) ? PROMISE_RESULT_CHANGE : PROMISE_RESULT_FAIL;
    }

    /* both files exist, but are they the same file? POSIX says  */
    /* the files could be on different devices, but unix doesn't */
    /* allow this behaviour so the tests below are theoretical... */

    if ((dsb.st_ino != ssb.st_ino) && (dsb.st_dev != ssb.st_dev))
    {
        Log(LOG_LEVEL_VERBOSE, "If this is POSIX, unable to determine if %s is hard link is correct", destination);
        Log(LOG_LEVEL_VERBOSE, "since it points to a different filesystem!");

        if ((dsb.st_mode == ssb.st_mode) && (dsb.st_size == ssb.st_size))
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Hard link (%s->%s) on different device APPEARS okay\n", destination,
                 to);
            return PROMISE_RESULT_NOOP;
        }
    }

    if ((dsb.st_ino == ssb.st_ino) && (dsb.st_dev == ssb.st_dev))
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Hard link (%s->%s) exists and is okay\n", destination, to);
        return PROMISE_RESULT_NOOP;
    }

    Log(LOG_LEVEL_INFO, "%s does not appear to be a hard link to %s", destination, to);

    if (!MoveObstruction(ctx, destination, attr, pp))
    {
        return PROMISE_RESULT_FAIL;
    }

    return MakeHardLink(ctx, destination, to, attr, pp) ? PROMISE_RESULT_CHANGE : PROMISE_RESULT_FAIL;
}
예제 #12
0
파일: files_links.c 프로젝트: baptr/core
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);
}
예제 #13
0
파일: nfs.c 프로젝트: bruvik/cfengine-core
int LoadMountInfo(Rlist **list)
/* This is, in fact, the most portable way to read the mount info! */
/* Depressing, isn't it? */
{
    FILE *pp;
    char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE];
    char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE], vbuff[CF_BUFSIZE];
    int i, nfs = false;

    for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++)
    {
        buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i];
    }

    buf1[i] = '\0';

    SetTimeOut(RPCTIMEOUT);

    if ((pp = cf_popen(buf1, "r")) == NULL)
    {
        CfOut(cf_error, "cf_popen", "Can't open %s\n", buf1);
        return false;
    }

    do
    {
        vbuff[0] = buf1[0] = buf2[0] = buf3[0] = source[0] = '\0';

        if (ferror(pp))         /* abortable */
        {
            CfOut(cf_error, "ferror", "Error getting mount info\n");
            break;
        }

        if (CfReadLine(vbuff, CF_BUFSIZE, pp) == -1)
        {
            FatalError("Error in CfReadLine");
        }

        if (ferror(pp))         /* abortable */
        {
            CfOut(cf_error, "ferror", "Error getting mount info\n");
            break;
        }

        if (strstr(vbuff, "nfs"))
        {
            nfs = true;
        }

        sscanf(vbuff, "%s%s%s", buf1, buf2, buf3);

        if ((vbuff[0] == '\0') || (vbuff[0] == '\n'))
        {
            break;
        }

        if (strstr(vbuff, "not responding"))
        {
            CfOut(cf_error, "", "%s\n", vbuff);
        }

        if (strstr(vbuff, "be root"))
        {
            CfOut(cf_error, "", "Mount access is denied. You must be root.\n");
            CfOut(cf_error, "", "Use the -n option to run safely.");
        }

        if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding")))
        {
            continue;
        }

        if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy")))
        {
            continue;
        }

        if (strstr(vbuff, "RPC"))
        {
            CfOut(cf_inform, "", "There was an RPC timeout. Aborting mount operations.\n");
            CfOut(cf_inform, "", "Session failed while trying to talk to remote host\n");
            CfOut(cf_inform, "", "%s\n", vbuff);
            cf_pclose(pp);
            return false;
        }

#if defined(__sun) || defined(__hpux)
        if (IsAbsoluteFileName(buf3))
        {
            strcpy(host, "localhost");
            strcpy(mounton, buf1);
        }
        else
        {
            sscanf(buf1, "%[^:]:%s", host, source);
            strcpy(mounton, buf1);
        }
#elif defined(_AIX)
        /* skip header */

        if (IsAbsoluteFileName(buf1))
        {
            strcpy(host, "localhost");
            strcpy(mounton, buf2);
        }
        else
        {
            strcpy(host, buf1);
            strcpy(source, buf1);
            strcpy(mounton, buf3);
        }
#elif defined(__CYGWIN__)
        strcpy(mounton, buf2);
        strcpy(host, buf1);
#elif defined(sco) || defined(__SCO_DS)
        CfOut(cf_error, "", "Don't understand SCO mount format, no data");
#else
        if (IsAbsoluteFileName(buf1))
        {
            strcpy(host, "localhost");
            strcpy(mounton, buf3);
        }
        else
        {
            sscanf(buf1, "%[^:]:%s", host, source);
            strcpy(mounton, buf3);
        }
#endif

        CfDebug("GOT: host=%s, source=%s, mounton=%s\n", host, source, mounton);

        if (nfs)
        {
            AugmentMountInfo(list, host, source, mounton, "nfs");
        }
        else
        {
            AugmentMountInfo(list, host, source, mounton, NULL);
        }
    }
    while (!feof(pp));

    alarm(0);
    signal(SIGALRM, SIG_DFL);
    cf_pclose(pp);
    return true;
}
예제 #14
0
int LoadMountInfo(Rlist **list)
/* This is, in fact, the most portable way to read the mount info! */
/* Depressing, isn't it? */
{
    FILE *pp;
    char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE];
    char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE], vbuff[CF_BUFSIZE];
    int i, nfs = false;

    for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++)
    {
        buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i];
    }

    buf1[i] = '\0';

    SetTimeOut(RPCTIMEOUT);

    if ((pp = cf_popen(buf1, "r")) == NULL)
    {
        CfOut(cf_error, "cf_popen", "Can't open %s\n", buf1);
        return false;
    }

    do
    {
        vbuff[0] = buf1[0] = buf2[0] = buf3[0] = source[0] = '\0';

        if (ferror(pp))         /* abortable */
        {
            CfOut(cf_error, "ferror", "Error getting mount info\n");
            break;
        }

        CfReadLine(vbuff, CF_BUFSIZE, pp);

        if (ferror(pp))         /* abortable */
        {
            CfOut(cf_error, "ferror", "Error getting mount info\n");
            break;
        }

        if (strstr(vbuff, "nfs"))
        {
            nfs = true;
        }

        sscanf(vbuff, "%s%s%s", buf1, buf2, buf3);

        if ((vbuff[0] == '\0') || (vbuff[0] == '\n'))
        {
            break;
        }

        if (strstr(vbuff, "not responding"))
        {
            CfOut(cf_error, "", "%s\n", vbuff);
        }

        if (strstr(vbuff, "be root"))
        {
            CfOut(cf_error, "", "Mount access is denied. You must be root.\n");
            CfOut(cf_error, "", "Use the -n option to run safely.");
        }

        if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding")))
        {
            continue;
        }

        if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy")))
        {
            continue;
        }

        if (strstr(vbuff, "RPC"))
        {
            CfOut(cf_inform, "", "There was an RPC timeout. Aborting mount operations.\n");
            CfOut(cf_inform, "", "Session failed while trying to talk to remote host\n");
            CfOut(cf_inform, "", "%s\n", vbuff);
            cf_pclose(pp);
            return false;
        }

        switch (VSYSTEMHARDCLASS)
        {
        case darwin:
        case linuxx:
        case unix_sv:
        case freebsd:
        case netbsd:
        case openbsd:
        case qnx:
        case crayos:
        case dragonfly:
            if (IsAbsoluteFileName(buf1))
            {
                strcpy(host, "localhost");
                strcpy(mounton, buf3);
            }
            else
            {
                sscanf(buf1, "%[^:]:%s", host, source);
                strcpy(mounton, buf3);
            }

            break;
        case solaris:

        case hp:
            if (IsAbsoluteFileName(buf3))
            {
                strcpy(host, "localhost");
                strcpy(mounton, buf1);
            }
            else
            {
                sscanf(buf1, "%[^:]:%s", host, source);
                strcpy(mounton, buf1);
            }

            break;
        case aix:
            /* skip header */

            if (IsAbsoluteFileName(buf1))
            {
                strcpy(host, "localhost");
                strcpy(mounton, buf2);
            }
            else
            {
                strcpy(host, buf1);
                strcpy(source, buf1);
                strcpy(mounton, buf3);
            }
            break;

        case cfnt:
            strcpy(mounton, buf2);
            strcpy(host, buf1);
            break;

        case cfsco:
            CfOut(cf_error, "", "Don't understand SCO mount format, no data");

        default:
            printf("cfengine software error: case %d = %s\n", VSYSTEMHARDCLASS, CLASSTEXT[VSYSTEMHARDCLASS]);
            FatalError("System error in GetMountInfo - no such class!");
        }

        CfDebug("GOT: host=%s, source=%s, mounton=%s\n", host, source, mounton);

        if (nfs)
        {
            AugmentMountInfo(list, host, source, mounton, "nfs");
        }
        else
        {
            AugmentMountInfo(list, host, source, mounton, NULL);
        }
    }
    while (!feof(pp));

    alarm(0);
    signal(SIGALRM, SIG_DFL);
    cf_pclose(pp);
    return true;
}
예제 #15
0
static char *InputLocation(char *filename)

{ static char wfilename[CF_BUFSIZE], path[CF_BUFSIZE];

if (MINUSF && (filename != VINPUTFILE) && IsFileOutsideDefaultRepository(VINPUTFILE) && !IsAbsoluteFileName(filename))
   {
   /* If -f assume included relative files are in same directory */
   strncpy(path,VINPUTFILE,CF_BUFSIZE-1);
   ChopLastNode(path);
   snprintf(wfilename,CF_BUFSIZE-1,"%s%c%s",path,FILE_SEPARATOR,filename);
   }
else if (IsFileOutsideDefaultRepository(filename))
   {
   strncpy(wfilename,filename,CF_BUFSIZE-1);
   }
else
   {
   snprintf(wfilename,CF_BUFSIZE-1,"%s%cinputs%c%s",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,filename);
   }

return MapName(wfilename);
}
예제 #16
0
파일: files_names.c 프로젝트: patuchov/core
bool IsFileOutsideDefaultRepository(const char *f)
{
    return (*f == '.') || (IsAbsoluteFileName(f));
}
예제 #17
0
파일: nfs.c 프로젝트: basvandervlies/core
bool LoadMountInfo(Seq *list)
/* This is, in fact, the most portable way to read the mount info! */
/* Depressing, isn't it? */
{
    FILE *pp;
    char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE];
    int i, nfs = false;

    for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++)
    {
        buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i];
    }

    buf1[i] = '\0';

    SetTimeOut(RPCTIMEOUT);

    if ((pp = cf_popen(buf1, "r", true)) == NULL)
    {
        Log(LOG_LEVEL_ERR, "Can't open '%s'. (cf_popen: %s)", buf1, GetErrorStr());
        return false;
    }

    size_t vbuff_size = CF_BUFSIZE;
    char *vbuff = xmalloc(vbuff_size);

    for (;;)
    {
        buf1[0] = buf2[0] = buf3[0] = '\0';
        nfs = false;

        ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp);
        if (res == -1)
        {
            if (!feof(pp))
            {
                Log(LOG_LEVEL_ERR, "Unable to read list of mounted filesystems. (fread: %s)", GetErrorStr());
                cf_pclose(pp);
                free(vbuff);
                return false;
            }
            else
            {
                break;
            }
        }

        if (strstr(vbuff, "nfs"))
        {
            nfs = true;
        }

        // security note: buff is CF_BUFSIZE, so that is the max that can be written to buf1, buf2 or buf3
        sscanf(vbuff, "%s%s%s", buf1, buf2, buf3);

        if ((vbuff[0] == '\0') || (vbuff[0] == '\n'))
        {
            break;
        }

        if (strstr(vbuff, "not responding"))
        {
            Log(LOG_LEVEL_ERR, "%s", vbuff);
        }

        if (strstr(vbuff, "be root"))
        {
            Log(LOG_LEVEL_ERR, "Mount access is denied. You must be root. Use the -n option to run safely");
        }

        if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding")))
        {
            continue;
        }

        if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy")))
        {
            continue;
        }

        if (strstr(vbuff, "RPC"))
        {
            Log(LOG_LEVEL_INFO, "There was an RPC timeout. Aborting mount operations.");
            Log(LOG_LEVEL_INFO, "Session failed while trying to talk to remote host");
            Log(LOG_LEVEL_INFO, "%s", vbuff);
            cf_pclose(pp);
            free(vbuff);
            return false;
        }

        // host: max FQDN is 255 chars (max IPv6 with IPv4 tunneling is 45 chars)
        // source, mounton: hardcoding max path length to 1023; longer is very unlikely
        char host[256], source[1024], mounton[1024];
        host[0] = source[0] = mounton[0] = '\0';


#if defined(__sun) || defined(__hpux)
        if (IsAbsoluteFileName(buf3))
        {
            strlcpy(host, "localhost", sizeof(host));
            strlcpy(mounton, buf1, sizeof(mounton));
        }
        else
        {
            sscanf(buf1, "%255[^:]:%1023s", host, source);
            strlcpy(mounton, buf1, sizeof(mounton));
        }
#elif defined(_AIX)
        /* skip header */

        if (IsAbsoluteFileName(buf1))
        {
            strlcpy(host, "localhost", sizeof(host));
            strlcpy(mounton, buf2, sizeof(mounton));
        }
        else
        {
            strlcpy(host, buf1, sizeof(host));
            strlcpy(source, buf1, sizeof(source));
            strlcpy(mounton, buf3, sizeof(mounton));
        }
#elif defined(__CYGWIN__)
        strlcpy(mounton, buf2, sizeof(mounton));
        strlcpy(host, buf1, sizeof(host));
#elif defined(sco) || defined(__SCO_DS)
        Log(LOG_LEVEL_ERR, "Don't understand SCO mount format, no data");
#else
        if (IsAbsoluteFileName(buf1))
        {
            strlcpy(host, "localhost", sizeof(host));
            strlcpy(mounton, buf3, sizeof(mounton));
        }
        else
        {
            sscanf(buf1, "%255[^:]:%1023s", host, source);
            strlcpy(mounton, buf3, sizeof(mounton));
        }
#endif

        Log(LOG_LEVEL_DEBUG, "LoadMountInfo: host '%s', source '%s', mounton '%s'", host, source, mounton);

        if (nfs)
        {
            AugmentMountInfo(list, host, source, mounton, "nfs");
        }
        else
        {
            AugmentMountInfo(list, host, source, mounton, NULL);
        }
    }

    free(vbuff);
    alarm(0);
    signal(SIGALRM, SIG_DFL);
    cf_pclose(pp);
    return true;
}
예제 #18
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);
}
예제 #19
0
static ActionResult RepairExec(EvalContext *ctx, Attributes a, Promise *pp)
{
    char line[CF_BUFSIZE], eventname[CF_BUFSIZE];
    char cmdline[CF_BUFSIZE];
    char comm[20];
    int outsourced, count = 0;
#if !defined(__MINGW32__)
    mode_t maskval = 0;
#endif
    FILE *pfp;
    char cmdOutBuf[CF_BUFSIZE];
    int cmdOutBufPos = 0;
    int lineOutLen;

    if (IsAbsoluteFileName(CommandArg0(pp->promiser)) || a.contain.shelltype == SHELL_TYPE_NONE)
    {
        if (!IsExecutable(CommandArg0(pp->promiser)))
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "'%s' promises to be executable but isn't", pp->promiser);

            if (strchr(pp->promiser, ' '))
            {
                Log(LOG_LEVEL_VERBOSE, "Paths with spaces must be inside escaped quoutes (e.g. \\\"%s\\\")", pp->promiser);
            }

            return ACTION_RESULT_FAILED;
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Promiser string contains a valid executable '%s' - ok", CommandArg0(pp->promiser));
        }
    }

    char timeout_str[CF_BUFSIZE];
    if (a.contain.timeout == CF_NOINT)
    {
        snprintf(timeout_str, CF_BUFSIZE, "no timeout");
    }
    else
    {
        snprintf(timeout_str, CF_BUFSIZE, "timeout=%ds", a.contain.timeout);
    }

    char owner_str[CF_BUFSIZE] = "";
    if (a.contain.owner != -1)
    {
        snprintf(owner_str, CF_BUFSIZE, ",uid=%ju", (uintmax_t)a.contain.owner);
    }

    char group_str[CF_BUFSIZE] = "";
    if (a.contain.group != -1)
    {
        snprintf(group_str, CF_BUFSIZE, ",gid=%ju", (uintmax_t)a.contain.group);
    }

    snprintf(cmdline, CF_BUFSIZE, "%s%s%s", pp->promiser, a.args ? " " : "", a.args ? a.args : "");

    Log(LOG_LEVEL_INFO, "Executing '%s%s%s' ... '%s'", timeout_str, owner_str, group_str, cmdline);

    BeginMeasure();

    if (DONTDO && (!a.contain.preview))
    {
        Log(LOG_LEVEL_ERR, "Would execute script '%s'", cmdline);
        return ACTION_RESULT_OK;
    }

    if (a.transaction.action != cfa_fix)
    {
        Log(LOG_LEVEL_ERR, "Command '%s' needs to be executed, but only warning was promised", cmdline);
        return ACTION_RESULT_OK;
    }

    CommandPrefix(cmdline, comm);

    if (a.transaction.background)
    {
#ifdef __MINGW32__
        outsourced = true;
#else
        Log(LOG_LEVEL_VERBOSE, "Backgrounding job '%s'", cmdline);
        outsourced = fork();
#endif
    }
    else
    {
        outsourced = false;
    }

    if (outsourced || (!a.transaction.background))    // work done here: either by child or non-background parent
    {
        if (a.contain.timeout != CF_NOINT)
        {
            SetTimeOut(a.contain.timeout);
        }

#ifndef __MINGW32__
        Log(LOG_LEVEL_VERBOSE, "(Setting umask to %jo)", (uintmax_t)a.contain.umask);
        maskval = umask(a.contain.umask);

        if (a.contain.umask == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "Programming '%s' running with umask 0! Use umask= to set", cmdline);
        }
#endif /* !__MINGW32__ */

        if (a.contain.shelltype == SHELL_TYPE_POWERSHELL)
        {
#ifdef __MINGW32__
            pfp =
                cf_popen_powershell_setuid(cmdline, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot,
                                           a.transaction.background);
#else // !__MINGW32__
            Log(LOG_LEVEL_ERR, "Powershell is only supported on Windows");
            return ACTION_RESULT_FAILED;
#endif // !__MINGW32__
        }
        else if (a.contain.shelltype == SHELL_TYPE_USE)
        {
            pfp =
                cf_popen_shsetuid(cmdline, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot,
                                  a.transaction.background);
        }
        else
        {
            pfp =
                cf_popensetuid(cmdline, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot,
                               a.transaction.background);
        }

        if (pfp == NULL)
        {
            Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmdline, GetErrorStr());
            return ACTION_RESULT_FAILED;
        }

        for (;;)
        {
            ssize_t res = CfReadLine(line, CF_BUFSIZE, pfp);

            if (res == 0)
            {
                break;
            }

            if (res == -1)
            {
                Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (fread: %s)", cmdline, GetErrorStr());
                cf_pclose(pfp);
                return ACTION_RESULT_FAILED;
            }

            if (strstr(line, "cfengine-die"))
            {
                break;
            }

            if (a.contain.preview)
            {
                PreviewProtocolLine(line, cmdline);
            }

            if (a.module)
            {
                ModuleProtocol(ctx, cmdline, line, !a.contain.nooutput, PromiseGetNamespace(pp));
            }
            else if ((!a.contain.nooutput) && (!EmptyString(line)))
            {
                lineOutLen = strlen(comm) + strlen(line) + 12;

                // if buffer is to small for this line, output it directly
                if (lineOutLen > sizeof(cmdOutBuf))
                {
                    Log(LOG_LEVEL_NOTICE, "Q: '%s': %s", comm, line);
                }
                else
                {
                    if (cmdOutBufPos + lineOutLen > sizeof(cmdOutBuf))
                    {
                        Log(LOG_LEVEL_NOTICE, "%s", cmdOutBuf);
                        cmdOutBufPos = 0;
                    }
                    sprintf(cmdOutBuf + cmdOutBufPos, "Q: \"...%s\": %s\n", comm, line);
                    cmdOutBufPos += (lineOutLen - 1);
                }
                count++;
            }
        }
#ifdef __MINGW32__
        if (outsourced)     // only get return value if we waited for command execution
        {
            cf_pclose(pfp);
        }
        else
#endif /* __MINGW32__ */
        {
            int ret = cf_pclose(pfp);

            if (ret == -1)
            {
                cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Finished script '%s' - failed (abnormal termination)", pp->promiser);
            }
            else
            {
                VerifyCommandRetcode(ctx, ret, true, a, pp);
            }
        }
    }

    if (count)
    {
        if (cmdOutBufPos)
        {
            Log(LOG_LEVEL_NOTICE, "%s", cmdOutBuf);
        }

        Log(LOG_LEVEL_INFO, "Last %d quoted lines were generated by promiser '%s'", count, cmdline);
    }

    if (a.contain.timeout != CF_NOINT)
    {
        alarm(0);
        signal(SIGALRM, SIG_DFL);
    }

    Log(LOG_LEVEL_INFO, "Completed execution of '%s'", cmdline);
#ifndef __MINGW32__
    umask(maskval);
#endif

    snprintf(eventname, CF_BUFSIZE - 1, "Exec(%s)", cmdline);

#ifndef __MINGW32__
    if ((a.transaction.background) && outsourced)
    {
        Log(LOG_LEVEL_VERBOSE, "Backgrounded command '%s' is done - exiting", cmdline);
        exit(0);
    }
#endif /* !__MINGW32__ */

    return ACTION_RESULT_OK;
}
예제 #20
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);
}
예제 #21
0
파일: files_links.c 프로젝트: baptr/core
PromiseResult VerifyLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp)
{
    char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE], absto[CF_BUFSIZE];
    struct stat sb;

    memset(to, 0, CF_BUFSIZE);

    if ((!IsAbsoluteFileName(source)) && (*source != '.'))        /* links without a directory reference */
    {
        snprintf(to, CF_BUFSIZE - 1, "./%s", source);
    }
    else
    {
        strncpy(to, source, CF_BUFSIZE - 1);
    }

    if (!IsAbsoluteFileName(to))        /* relative path, must still check if exists */
    {
        Log(LOG_LEVEL_DEBUG, "Relative link destination detected '%s'", to);
        strcpy(absto, AbsLinkPath(destination, to));
        Log(LOG_LEVEL_DEBUG, "Absolute path to relative link '%s', '%s'", absto, destination);
    }
    else
    {
        strcpy(absto, to);
    }

    bool source_file_exists = true;

    if (stat(absto, &sb) == -1)
    {
        Log(LOG_LEVEL_DEBUG, "No source file");
        source_file_exists = false;
    }

    if ((!source_file_exists) && (attr.link.when_no_file != cfa_force) && (attr.link.when_no_file != cfa_delete))
    {
        Log(LOG_LEVEL_INFO, "Source %s for linking is absent", absto);
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, attr, "Unable to create link %s -> %s, no source", destination, to);
        return PROMISE_RESULT_WARN;
    }

    if ((!source_file_exists) && (attr.link.when_no_file == cfa_delete))
    {
        KillGhostLink(ctx, destination, attr, pp);
        return PROMISE_RESULT_CHANGE;
    }

    memset(linkbuf, 0, CF_BUFSIZE);

    if (readlink(destination, linkbuf, CF_BUFSIZE - 1) == -1)
    {

        if (!MakeParentDirectory2(destination, attr.move_obstructions, EnforcePromise(attr.transaction.action)))
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create parent directory of link %s -> %s (enforce=%d)",
                 destination, to, EnforcePromise(attr.transaction.action));
            return PROMISE_RESULT_FAIL;
        }
        else
        {
            if (!MoveObstruction(ctx, destination, attr, pp))
            {
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, attr, "Unable to create link %s -> %s", destination, to);
                return PROMISE_RESULT_FAIL;
            }

            return MakeLink(ctx, destination, source, attr, pp) ? PROMISE_RESULT_CHANGE : PROMISE_RESULT_FAIL;
        }
    }
    else
    {
        int ok = false;

        if ((attr.link.link_type == FILE_LINK_TYPE_SYMLINK) && (strcmp(linkbuf, to) != 0) && (strcmp(linkbuf, source) != 0))
        {
            ok = true;
        }
        else if (strcmp(linkbuf, source) != 0)
        {
            ok = true;
        }

        if (ok)
        {
            if (attr.move_obstructions)
            {
                if (!DONTDO)
                {
                    cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Overriding incorrect link %s\n", destination);

                    if (unlink(destination) == -1)
                    {
                        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, attr, "Link %s points to %s not %s - error removing link",
                             destination, linkbuf, to);
                        return PROMISE_RESULT_FAIL;
                    }

                    return MakeLink(ctx, destination, source, attr, pp);
                }
                else
                {
                    Log(LOG_LEVEL_ERR, "Must remove incorrect link %s", destination);
                    return PROMISE_RESULT_NOOP;
                }
            }
            else
            {
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, attr, "Link %s points to %s not %s - not authorized to override",
                     destination, linkbuf, to);
                return true;
            }
        }
        else
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Link %s points to %s - promise kept", destination, source);
            return PROMISE_RESULT_NOOP;
        }
    }
}
예제 #22
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;
}
예제 #23
0
파일: files_lib.c 프로젝트: rcorrieri/core
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;
}