void PListStore(PList_p where, IntOrP val) { PList_p handle = PListCellAlloc(); handle->key = val; PListInsert(where, handle); }
static bool MakeTargetDir(char *Name, PListEntry **Dirs) { char *Basename; PListEntry *Dir; struct stat Stat; int Result; if ((Basename = strrchr(Name, '/')) == NULL) return true; *Basename = '\0'; if ((Dir = PListFind(*Dirs, Name)) != NULL) { *Basename = '/'; Dir->pe_DirEmpty = false; return true; } if (!MakeTargetDir(Name, Dirs)) { *Basename = '/'; return false; } if (stat(Name, &Stat) == 0) { Result = S_ISDIR(Stat.st_mode); } else if (errno != ENOENT) { Result = false; } else if ((Result = (mkdir(Name, S_IRWXU|S_IRWXG|S_IRWXO) == 0))) { (void)PListInsert(Dirs, Name); } *Basename = '/'; return Result; }
static void ProcessRPM(const char *filename, PListEntry **files, PListEntry **dirs, char **ignore, const char *prefix, int stripcount) { int fd; FileHandle *in; PListEntry *last; if ((fd = open(filename, O_RDONLY, 0)) < 0) { perror(filename); exit(EXIT_FAILURE); } if (!IsRPMFile(fd)) { (void)fprintf(stderr, "%s: file is not an RPM package.\n", filename); exit(EXIT_FAILURE); } if ((in = OpenRPM(&fd)) == NULL) { (void)fprintf(stderr, "%s: cannot get RPM data.\n", filename); exit(EXIT_FAILURE); } if (fd >= 0) { (void)close(fd); fd = -1; } last = NULL; for (;;) { unsigned long fields[CPIO_NUM_HEADERS]; char *name; mode_t mode; unsigned long length; if (!GetCPIOHeader(in, fields, &name)) { (void)fprintf(stderr, "%s: error in cpio header.\n", filename); exit(EXIT_FAILURE); } if (strcmp(name, CPIO_END_MARKER) == 0) { free(name); break; } if (*name == '\0') fields[CPIO_HDR_MODE] = 0; if (ignore != NULL) { char **ptr; for (ptr = ignore; *ptr != NULL; ptr++) { if (CheckPrefix(*ptr, name)) { fields[CPIO_HDR_MODE] = 0; break; } } } if (fields[CPIO_HDR_MODE] != 0 && !StripPrefix(name, stripcount)) { (void)fprintf(stderr, "%s: Leading path to strip too " "big (-s %d)\n", filename, stripcount); exit(EXIT_FAILURE); } if (prefix != NULL) { char *fullname; fullname = StrCat(prefix, name); free(name); name = fullname; } mode = ConvertMode(fields[CPIO_HDR_MODE]); length = fields[CPIO_HDR_FILESIZE]; switch (fields[CPIO_HDR_MODE] & CP_IFMT) { case C_ISDIR: { PListEntry *dir; bool old_dir; if (length != 0) { (void)fprintf(stderr, "%s: error in cpio file.\n", filename); exit(EXIT_FAILURE); } if (!MakeTargetDir(name, dirs)) { (void)fprintf(stderr, "%s: can't create parent " "directories for \"%s\".\n", filename, name); exit(EXIT_FAILURE); } if (!MakeDir(name, mode, &old_dir)) { (void)fprintf(stderr, "%s: can't create directory " "\"%s\".\n", filename, name); exit(EXIT_FAILURE); } if (!old_dir) { dir = PListInsert(dirs, name); dir->pe_DirEmpty = true; } break; } case C_ISLNK: { char *link_target; if ((link_target = GetData(in, length)) == NULL) { (void)fprintf(stderr, "%s: error in cpio file.\n", filename); exit(EXIT_FAILURE); } if (!MakeTargetDir(name, dirs)) { (void)fprintf(stderr, "%s: can't create parent " "directories for \"%s\".\n", filename, name); exit(EXIT_FAILURE); } if (*link_target == '/') { char *ptr; (void)memmove(link_target, link_target + 1, strlen(link_target)); ptr = name; if (prefix != NULL) ptr += strlen(prefix); while ((ptr = strchr(ptr, '/')) != NULL) { char *new_link_target; new_link_target = StrCat("../", link_target); free(link_target); link_target = new_link_target; ptr++; } } if (!MakeSymLink(link_target, name)) { (void)fprintf(stderr, "%s: can't create symbolic link " "\"%s\".\n", filename, name); exit(EXIT_FAILURE); } PListInsert(files, name)->pe_Link = link_target; break; } case C_ISREG: if (!MakeTargetDir(name, dirs)) { (void)fprintf(stderr, "%s: can't create parent " "directories for \"%s\".\n", filename, name); exit(EXIT_FAILURE); } if ((last != NULL) && (last->pe_INode != fields[CPIO_HDR_INODE])) { last = NULL; } if (!WriteFile(in, name, mode, length, (last != NULL)? last->pe_Name : NULL)) { (void)fprintf(stderr, "%s: can't write file \"%s\".\n", filename, name); exit(EXIT_FAILURE); } last = PListInsert(files, name); last->pe_INode = fields[CPIO_HDR_INODE]; break; default: if (length > 0 && !SkipAndAlign(in, length)) { (void)fprintf(stderr, "%s: error in cpio file.\n", filename); exit(EXIT_FAILURE); } } free(name); } FileHandleClose(in); }