main(int argc, char** argv) { Ardir_t* dir; Ardirent_t* ent; long touch; char* file; touch = 0; while (file = *++argv) { if (!strcmp(file, "-t") && *(argv + 1)) touch = strtol(*++argv, NiL, 0); else if (dir = ardiropen(file, NiL, touch ? ARDIR_UPDATE : 0)) { sfprintf(sfstdout, "%s: type=%s truncate=%d%s\n", file, dir->meth->name, dir->truncate, (dir->flags & ARDIR_RANLIB) ? " ranlib" : ""); while (ent = ardirnext(dir)) { if (touch) { ent->mtime = touch; ardirchange(dir, ent); sfprintf(sfstdout, "touch %s\n", ent->name); } else sfprintf(sfstdout, "%s %8u %8u %8llu %8llu %s %s\n", fmtmode(ent->mode, 1), ent->uid, ent->gid, ent->size, ent->offset, fmttime("%k", ent->mtime), ent->name); } if (ardirclose(dir)) error(2, "%s: archive read error", file); } else error(ERROR_SYSTEM|2, "%s: not an archive", file); } return 0; }
Ardir_t* ardiropen(const char* file, Ardirmeth_t* meth, int flags) { Ardir_t* ar; char* skip; off_t pos; ssize_t n = 0; char buf[1024]; if (!(ar = newof(0, Ardir_t, 1, strlen(file) + 1))) return 0; strcpy(ar->path = (char*)(ar + 1), file); ar->flags = flags; if (((ar->fd = open(file, (flags & ARDIR_CREATE) ? (O_CREAT|O_TRUNC|O_RDWR|O_BINARY|O_cloexec) : (flags & ARDIR_UPDATE) ? (O_RDWR|O_BINARY|O_cloexec) : (O_RDONLY|O_BINARY|O_cloexec))) < 0 || fstat(ar->fd, &ar->st) || !S_ISREG(ar->st.st_mode)) && (!meth || !(flags & ARDIR_FORCE))) { ardirclose(ar); return 0; } if (ar->fd >= 0 && ((pos = lseek(ar->fd, (off_t)0, SEEK_CUR)) < 0 || (n = read(ar->fd, buf, sizeof(buf))) < 0 || lseek(ar->fd, pos, SEEK_SET) != pos)) { ardirclose(ar); return 0; } if (!(ar->meth = meth)) { skip = getenv("_AST_DEBUG_ARDIR_SKIP"); for (meth = ar_first_method; ar->meth = meth; meth = meth->next) if ((!skip || !strmatch(meth->name, skip)) && !(*meth->openf)(ar, buf, n)) break; if (!(ar->meth = meth)) { ardirclose(ar); return 0; } } else if ((*meth->openf)(ar, buf, n)) { ardirclose(ar); return 0; } return ar; }
static int ar_done(Pax_t* pax, register Archive_t* ap) { register Ar_t* ar = (Ar_t*)ap->data; if (ar) { if (ar->dir) ardirclose(ar->dir); free(ar); ap->data = 0; } return 0; }
static int ar_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, register File_t* f, unsigned char* buf, size_t size) { Ar_t* ar; Ardir_t* dir; if (!(dir = ardiropen(ap->name, NiL, 0))) return 0; if (!(ar = newof(0, Ar_t, 1, 0))) { ardirclose(dir); nospace(); return -1; } ap->data = ar; ar->dir = dir; ap->type = (char*)dir->meth->name; return 1; }