On 20 May 2011 21:51, Nick <[email protected]> wrote:
> One thing which could be considered would be allowing specifying
> file / directory names on argv.
> Another feature which would be nice would be stripping of leading /
> and .. from path names when creating and extracting archives.
Attached!
I also fixed a bug in my patch, and a bug in tip.
cls
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 <dirent.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -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;