コード例 #1
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;
}
コード例 #2
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;
        }
    }
}
コード例 #3
0
ファイル: link.c プロジェクト: kbarber/cfng
/* should return true if 'to' found */
int
LinkFiles(char *from,char *to_tmp,
        struct Item *inclusions,struct Item *exclusions,struct Item *copy,
        short nofile,struct Link *ptr)
{
    struct stat buf,savebuf;
    char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE];
    char saved[CF_BUFSIZE],absto[CF_BUFSIZE],*lastnode;
    struct UidList fakeuid;
    struct Image ip;
    char stamp[CF_BUFSIZE];
    time_t STAMPNOW;
    STAMPNOW = time((time_t *)NULL);

    memset(to,0,CF_BUFSIZE);
    memset(&ip,0, sizeof(ip));

    /* links without a directory reference */
    if ((*to_tmp != '/') && (*to_tmp != '.')) {
        strcpy(to,"./");
    }

    if (strlen(to_tmp)+3 > CF_BUFSIZE) {
        printf("%s: CF_BUFSIZE boundaries exceeded in LinkFiles(%s->%s)\n",
                g_vprefix,from,to_tmp);
        return false;
    }

    strcat(to,to_tmp);

    Debug2("Linkfiles(%s,%s)\n",from,to);

    for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { }

    lastnode++;

    if (IgnoredOrExcluded(links,lastnode,inclusions,exclusions)) {
        Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from);
        return true;
    }

    if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) {
        fakeuid.uid = CF_SAME_OWNER;
        fakeuid.next = NULL;
        ip.plus = CF_SAMEMODE;
        ip.minus = CF_SAMEMODE;
        ip.uid = &fakeuid;
        ip.gid = (struct GidList *) &fakeuid;
        ip.action = "do";
        ip.recurse = 0;
        ip.type = 't';
        ip.defines = ptr->defines;
        ip.elsedef = ptr->elsedef;
        ip.backup = true;
        ip.exclusions = NULL;
        ip.inclusions = NULL;
        ip.symlink = NULL;
        ip.classes = NULL;
        ip.plus_flags = 0;
        ip.size = CF_NOSIZE;
        ip.linktype = 's';
        ip.minus_flags = 0;
        ip.server = strdup("localhost");
        Verbose("%s: Link item %s marked for copying instead\n", 
                g_vprefix, from);
        MakeDirectoriesFor(to,'n');
        CheckImage(to,from,&ip);
        free(ip.server);
        return true;
    }

    /* relative path, must still check if exists */
    if (*to != '/') {
        Debug("Relative link destination detected: %s\n",to);
        strcpy(absto,AbsLinkPath(from,to));
        Debug("Absolute path to relative link = %s, from %s\n",absto,from);
    } else {
        strcpy(absto,to);
    }

    if (!nofile) {
        if (stat(absto,&buf) == -1) {
            /* no error warning, since the higher level routine uses this */
            return(false);
        }
    }

    Debug2("Trying to link %s -> %s (%s)\n",from,to,absto);

    if (lstat(from,&buf) == 0) {
        if (! S_ISLNK(buf.st_mode) && ! g_enforcelinks) {
            snprintf(g_output,CF_BUFSIZE*2,"Error linking %s -> %s\n",from,to);
            CfLog(cfsilent,g_output,"");

            snprintf(g_output, CF_BUFSIZE*2,
                    "Cannot make link: %s exists and is not a link! "
                    "(uid %d)\n", from, buf.st_uid);

            CfLog(cfsilent,g_output,"");
            return(true);
        }

        if (S_ISREG(buf.st_mode) && g_enforcelinks) {
            snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s%s\n",
                    from, from, CF_SAVED);
            CfLog(cfsilent,g_output,"");

            if (g_dontdo) {
                return true;
            }

            saved[0] = '\0';
            strcpy(saved,from);

            sprintf(stamp, "_%d_%s",
                    g_cfstarttime, CanonifyName(ctime(&STAMPNOW)));
            strcat(saved,stamp);

            strcat(saved,CF_SAVED);

            if (rename(from,saved) == -1) {
                snprintf(g_output, CF_BUFSIZE*2,
                        "Can't rename %s to %s\n", from,saved);
                CfLog(cferror,g_output,"rename");
                return(true);
            }

            if (Repository(saved,g_vrepository)) {
                unlink(saved);
            }
        }

        if (S_ISDIR(buf.st_mode) && g_enforcelinks) {
            snprintf(g_output,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n",
                    from,from,CF_SAVED);
            CfLog(cfsilent,g_output,"");

            if (g_dontdo) {
                return true;
            }

            saved[0] = '\0';
            strcpy(saved,from);

            sprintf(stamp, "_%d_%s",
                    g_cfstarttime, CanonifyName(ctime(&STAMPNOW)));
            strcat(saved,stamp);

            strcat(saved,CF_SAVED);
            strcat(saved,".dir");

            if (stat(saved,&savebuf) != -1) {

                snprintf(g_output,CF_BUFSIZE*2,
                        "Couldn't save directory %s, "
                        "since %s exists already\n",
                        from,saved);

                CfLog(cferror,g_output,"");

                snprintf(g_output,CF_BUFSIZE*2,
                        "Unable to force link to "
                        "existing directory %s\n",from);

                CfLog(cferror,g_output,"");
                return true;
            }

            if (rename(from,saved) == -1) {
                snprintf(g_output, CF_BUFSIZE*2, 
                        "Can't rename %s to %s\n", from,saved);
                CfLog(cferror,g_output,"rename");
                return(true);
            }
        }
    }

    memset(linkbuf,0,CF_BUFSIZE);

    if (readlink(from,linkbuf,CF_BUFSIZE-1) == -1) {
        /* link doesn't exist */
        if (! MakeDirectoriesFor(from,'n')) {

            snprintf(g_output,CF_BUFSIZE*2,
                    "Couldn't build directory tree up to %s!\n",from);

            CfLog(cfsilent,g_output,"");

            snprintf(g_output,CF_BUFSIZE*2,
                    "One element was a plain file, not a directory!\n");

            CfLog(cfsilent,g_output,"");
            return(true);
        }
    } else {
        int off1 = 0, off2 = 0;

        DeleteSlash(linkbuf);

        /* Ignore ./ at beginning */
        if (strncmp(linkbuf,"./",2) == 0) {
            off1 = 2;
        }

        if (strncmp(to,"./",2) == 0) {
            off2 = 2;
        }

        if (strcmp(linkbuf+off1,to+off2) != 0) {
            if (g_enforcelinks) {
                snprintf(g_output,CF_BUFSIZE*2,"Removing link %s\n",from);
                CfLog(cfinform,g_output,"");

                if (!g_dontdo) {
                    if (unlink(from) == -1) {
                        perror("unlink");
                        return true;
                    }

                    return DoLink(from,to,ptr->defines);
                }
            } else {

                snprintf(g_output,CF_BUFSIZE*2,
                        "Old link %s points somewhere else. Doing nothing!\n",
                        from);

                CfLog(cfsilent,g_output,"");

                snprintf(g_output, CF_BUFSIZE*2,
                        "(Link points to %s not %s)\n\n",
                        linkbuf,to);

                CfLog(cfsilent,g_output,"");
                return(true);
            }
        } else {
            snprintf(g_output, CF_BUFSIZE*2,
                    "Link (%s->%s) exists.\n", from, to_tmp);
            CfLog(cfverbose,g_output,"");

            if (!nofile) {

                /* Check whether link points somewhere */
                KillOldLink(from,ptr->defines);

                return true;
            }

            AddMultipleClasses(ptr->elsedef);
            return(true);
        }
    }

    return DoLink(from,to,ptr->defines);
}