Exemple #1
0
Fichier : fsm.c Projet : nforro/rpm
static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
		     rpmpsm psm, int nodigest, int *setmeta,
		     int * firsthardlink, FD_t *firstlinkfile)
{
    int rc = 0;
    int numHardlinks = rpmfiFNlink(fi);

    if (numHardlinks > 1) {
	/* Create first hardlinked file empty */
	if (*firsthardlink < 0) {
	    *firsthardlink = rpmfiFX(fi);
	    rc = wfd_open(firstlinkfile, dest);
	} else {
	    /* Create hard links for others */
	    char *fn = rpmfilesFN(files, *firsthardlink);
	    rc = link(fn, dest);
	    if (rc < 0) {
		rc = RPMERR_LINK_FAILED;
	    }
	    free(fn);
	}
    }
    /* Write normal files or fill the last hardlinked (already
       existing) file with content */
    if (numHardlinks<=1) {
	if (!rc)
	    rc = expandRegular(fi, dest, psm, nodigest);
    } else if (rpmfiArchiveHasContent(fi)) {
	if (!rc)
	    rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
	wfd_close(firstlinkfile);
	*firsthardlink = -1;
    } else {
	*setmeta = 0;
    }

    return rc;
}
Exemple #2
0
int myCpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings,
                         int numMappings, cpioCallback cb, void * cbData,
                         const char ** failedFile) {
    struct cpioHeader ch;
    struct ourfd fd;
    int rc = 0;
    int linkNum = 0;
    struct cpioFileMapping * map = NULL;
    struct cpioFileMapping needle;
    mode_t cpioMode;
    int olderr;
    struct cpioCallbackInfo cbInfo;
    struct hardLink * links = NULL;
    struct hardLink * li = NULL;

    fd.fd = stream;
    fd.pos = 0;

    *failedFile = NULL;

    do {
        if ((rc = getNextHeader(&fd, &ch, NULL))) {
            fprintf(stderr, _("error %d reading header: %s\n"), rc,
                    myCpioStrerror(rc));
            return CPIOERR_BAD_HEADER;
        }

        if (!strcmp(ch.path, TRAILER)) {
            free(ch.path);
            break;
        }

        if (mappings) {
            needle.archivePath = ch.path;
            map = bsearch(&needle, mappings, numMappings, sizeof(needle),
                          myCpioFileMapCmp);
        }

        if (mappings && !map) {
            eatBytes(&fd, ch.size);
        } else {
            cpioMode = ch.mode;

            if (map) {
                if (map->mapFlags & CPIO_MAP_PATH) {
                    free(ch.path);
                    ch.path = strdup(map->fsPath);
                }

                if (map->mapFlags & CPIO_MAP_MODE)
                    ch.mode = map->finalMode;
                if (map->mapFlags & CPIO_MAP_UID)
                    ch.uid = map->finalUid;
                if (map->mapFlags & CPIO_MAP_GID)
                    ch.gid = map->finalGid;
            }

            /* This won't get hard linked symlinks right, but I can't seem
               to create those anyway */

            if (S_ISREG(ch.mode) && ch.nlink > 1) {
                li = links;
                for (li = links; li; li = li->next) {
                    if (li->inode == ch.inode && li->dev == ch.dev) break;
                }

                if (!li) {
                    li = malloc(sizeof(*li));
                    li->inode = ch.inode;
                    li->dev = ch.dev;
                    li->nlink = ch.nlink;
                    li->linksLeft = ch.nlink;
                    li->createdPath = -1;
                    li->files = calloc(sizeof(char *), li->nlink);
                    li->next = links;
                    links = li;
                }

                for (linkNum = 0; linkNum < li->nlink; linkNum++)
                    if (!li->files[linkNum]) break;
                li->files[linkNum] = strdup(ch.path);
            }

            if ((ch.nlink > 1) && S_ISREG(ch.mode) && !ch.size &&
                    li->createdPath == -1) {
                /* defer file creation */
            } else if ((ch.nlink > 1) && S_ISREG(ch.mode) &&
                       (li->createdPath != -1)) {
                createLinks(li, failedFile);

                /* this only happens for cpio archives which contain
                   hardlinks w/ the contents of each hardlink being
                   listed (intead of the data being given just once. This
                   shouldn't happen, but I've made it happen w/ buggy
                   code, so what the heck? GNU cpio handles this well fwiw */
                if (ch.size) eatBytes(&fd, ch.size);
            } else {
                rc = checkDirectory(ch.path);

                if (!rc) {
                    if (S_ISREG(ch.mode))
                        rc = expandRegular(&fd, &ch, cb, cbData);
                    else if (S_ISDIR(ch.mode))
                        rc = createDirectory(ch.path, 000);
                    else if (S_ISLNK(ch.mode))
                        rc = expandSymlink(&fd, &ch);
                    else if (S_ISFIFO(ch.mode))
                        rc = expandFifo(&fd, &ch);
                    else if (S_ISCHR(ch.mode) || S_ISBLK(ch.mode))
                        rc = expandDevice(&fd, &ch);
                    else if (S_ISSOCK(ch.mode)) {
                        /* this mimicks cpio but probably isnt' right */
                        rc = expandFifo(&fd, &ch);
                    } else {
                        rc = CPIOERR_INTERNAL;
                    }
                }

                if (!rc)
                    rc = setInfo(&ch);

                if (S_ISREG(ch.mode) && ch.nlink > 1) {
                    li->createdPath = linkNum;
                    li->linksLeft--;
                    rc = createLinks(li, failedFile);
                }
            }

            if (rc && !*failedFile) {
                *failedFile = strdup(ch.path);

                olderr = errno;
                unlink(ch.path);
                errno = olderr;
            }
        }

        padinfd(&fd, 4);

        if (!rc && cb) {
            cbInfo.file = ch.path;
            cbInfo.fileSize = ch.size;
            cbInfo.fileComplete = ch.size;
            cbInfo.bytesProcessed = fd.pos;
            cb(&cbInfo, cbData);
        }

        free(ch.path);
    } while (1 && !rc);

    li = links;
    while (li && !rc) {
        if (li->linksLeft) {
            if (li->createdPath == -1)
                rc = CPIOERR_INTERNAL;
            else
                rc = createLinks(li, failedFile);
        }

        freeLink(li);

        links = li;
        li = li->next;
        free(links);
        links = li;
    }

    li = links;
    /* if an error got us here links will still be eating some memory */
    while (li) {
        freeLink(li);
        links = li;
        li = li->next;
        free(links);
    }

    return rc;
}