diff -r fadca8e2d4d0 sltar.c --- a/sltar.c Fri May 20 22:12:58 2011 +0100 +++ b/sltar.c Fri May 20 23:39:53 2011 +0100 @@ -3,6 +3,7 @@ * * See LICENSE for further informations */ +#include #include #include #include @@ -14,22 +15,23 @@ SUM = 148, TYPE = 156, LINK = 157, MAJ = 329, MIN = 337, END = 512 }; +static int appenddir(const char *dir); static int append(const char *file); static int cksum(unsigned char *b); -static int create(void); -static int xtract(char a); +static int create(int argc, char *argv[]); +static int xtract(int argc, char *argv[], char a); int main(int argc, char *argv[]) { char a; - if(argc == 2 && strlen(argv[1]) == 1) + if(argc > 1 && strlen(argv[1]) == 1) switch((a = argv[1][0])) { case 'c': - return create(); + return create(argc-2, &argv[2]); case 'x': case 't': - return xtract(a); + return xtract(argc-2, &argv[2], a); } /* should not reach */ @@ -44,7 +46,7 @@ char buf[END]; size_t n; struct stat st; - FILE *fp; + FILE *fp = NULL; if(stat(file, &st) == -1) { fprintf(stderr, "%s: cannot stat\n", file); @@ -78,23 +80,45 @@ fprintf(stderr, "%s: unsupported file type\n", file); return EXIT_FAILURE; } - if(buf[TYPE] == '3' || buf[TYPE] == '4') { + if(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { snprintf(&buf[MAJ], 8, "%07o", major(st.st_rdev)); snprintf(&buf[MIN], 8, "%07o", minor(st.st_rdev)); } snprintf(&buf[SUM], 8, "%06o", cksum((unsigned char *)buf)); buf[SUM+7] = ' '; - if(!(fp = fopen(file, "r"))) { + if(S_ISREG(st.st_mode) && !(fp = fopen(file, "r"))) { fprintf(stderr, "%s: cannot open\n", file); return EXIT_FAILURE; } - for(n = 1; n > 0; n = fread(buf, 1, sizeof buf, fp)) { + for(n = 1; n > 0; n = fp ? fread(buf, 1, sizeof buf, fp) : 0) { fwrite(buf, sizeof buf, 1, stdout); memset(buf, 0, sizeof buf); } - fclose(fp); - return EXIT_SUCCESS; + if(fp) + fclose(fp); + return S_ISDIR(st.st_mode) ? appenddir(file) : EXIT_SUCCESS; +} + +int +appenddir(const char *dir) +{ + char buf[BUFSIZ]; + int ret = EXIT_SUCCESS; + struct dirent *d; + DIR *dp; + + if(!(dp = opendir(dir))) { + fprintf(stderr, "%s: cannot opendir\n", dir); + return EXIT_FAILURE; + } + while((d = readdir(dp))) + if(strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) { + snprintf(buf, sizeof buf, "%s/%s", dir, d->d_name); + if(append(buf) == EXIT_FAILURE) + ret = EXIT_FAILURE; + } + return ret; } int @@ -108,32 +132,47 @@ } int -create(void) { +create(int argc, char *argv[]) { char buf[BUFSIZ], *p; - int ret = EXIT_SUCCESS; + int i, ret = EXIT_SUCCESS; - while(fgets(buf, sizeof buf, stdin)) { - if((p = strchr(buf, '\n'))) + for(i = 0; argc ? i < argc : fgets(buf, sizeof buf, stdin) != NULL; i++) { + if(!argc && (p = strchr(buf, '\n'))) *p = '\0'; - if(append(buf) == EXIT_FAILURE) + if(append(argc ? argv[i] : buf) == EXIT_FAILURE) ret = EXIT_FAILURE; } return ret; } int -xtract(char a) { - int l; - char b[END],fname[101],lname[101]; +xtract(int argc, char *argv[], char a) { + int i, l; + char b[END], fname[101], lname[101], *p; FILE *f = NULL; for(lname[100] = fname[100] = l = 0; fread(b,END,1,stdin); l -= END) - if(l <= 0) { + if(l <= 0) { if(*b == '\0') break; - memcpy(fname,b,100); + for(p = b; *p == '/'; p++); + memcpy(fname, p, 100); + + for(i = 0; i < argc; i++) + if(!strcmp(argv[i], fname)) + break; + memcpy(lname,b + LINK,100); - l = strtoull(b + SIZE,0,8) + END; + + if(b[TYPE] == '0') + l = strtoull(b + SIZE,0,8) + END; + else + l = END; + if(argc && i == argc) { + if(a == 'x' && b[TYPE] == '0' && !(f = fopen("/dev/null", "w"))) + perror("/dev/null"); + continue; + } if(a == 't') { puts(fname); continue;