#include #include #include #include #include #include #include #include void usage (char * p, char * cond) { fprintf (stderr, "usage: %s [ -c | -e ] -f archive file ...\n", p); fprintf (stderr, "Condition was %s\n", cond); exit (1); } #define USAGEIF(X) if (X) { usage (argv[0], #X); } #define EXTRACT 1 #define CREATE 2 struct header { off_t filesize; off_t namesize; }; void do_write (int fd, void * p, int len) { int ret = write (fd, p, len); if (ret < 0) { perror ("write"); exit (1); } if (ret != len) { fprintf (stderr, "write incomplete. aborting\n"); exit (1); } } void do_read (int fd, void * p, int len) { int ret = read (fd, p, len); if (ret < 0) { perror ("read"); exit (1); } if (ret != len) { fprintf (stderr, "read incomplete. aborting\n"); exit (1); } } void copy_one (int src, int dest, off_t len) { char buf[100]; int tmp; while (len) { tmp = 100; if (tmp > len) { tmp = len; } do_read (src, buf, tmp); do_write (dest, buf, tmp); len -= tmp; } } int main (int argc, char * argv[]) { char * archive = NULL; struct header head; int afd = -1; int mode = -1; int optc; int i; opterr = 0; while (1) { optc = getopt (argc, argv, "cef:"); if (optc < 0) { break; } switch (optc) { case 'c': USAGEIF(mode >= 0); mode = CREATE; break; case 'e': USAGEIF(mode >= 0); mode = EXTRACT; break; case 'f': USAGEIF(archive); archive = optarg; break; default: USAGEIF(1); } } USAGEIF(mode < 0); USAGEIF(archive == NULL); switch (mode) { case EXTRACT: afd = open (archive, O_RDONLY); break; case CREATE: afd = open (archive, O_WRONLY|O_CREAT|O_EXCL, 0666); break; default: assert (0); } if (afd < 0) { perror ("open"); exit (1); } if (mode == EXTRACT) { USAGEIF(optind < argc); } if (mode == CREATE) { struct stat statbuf; char buf[10]; ino_t archive_inode; dev_t archive_dev; if (fstat (afd, &statbuf) < 0) { perror ("fstat (on archive)"); exit (1); } archive_inode = statbuf.st_ino; archive_dev = statbuf.st_dev; for (i=optind; i