#if 0 gcc -s -O2 -o ~/bin/har -Wno-unused-result har.c exit #endif /* Hamster archiver Public domain c = Create d = Delete l = Lowercase o = Extract to stdout r = Rename s = Safe t = List w = Wildcards u = Uppercase x = Extract to files */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define fatal(...) do { fprintf(stderr,__VA_ARGS__); putchar('\n'); exit(1); } while(0) static const char safe[128]={ [0]=1, ['0'...'9']=1, ['A'...'Z']=1, ['a'...'z']=1, ['-']=1, ['_']=1, ['.']=1, ['/']=1, ['+']=1, }; static char opt[128]; static char name[256]; static unsigned long size; static int argc; static char**argv; static void process_lump(int a) { int n=0; int d=1; int c,o; FILE*fp; FILE*in; if(opt['c']) { strcpy(name,argv[a]); in=fopen(argv[a+opt['r']],"r"); if(!in) { perror(argv[a+opt['r']]); fatal("Cannot open file for input"); } if(opt['u']) { for(n=0;name[n];n++) if(name[n]>='a' && name[n]<='z') name[n]+='A'-'a'; } else if(opt['l']) { for(n=0;name[n];n++) if(name[n]>='A' && name[n]<='Z') name[n]+='a'-'A'; } fseek(in,0,SEEK_END); size=ftell(in); fseek(in,0,SEEK_SET); o=1; } else { in=stdin; for(;;) { c=fgetc(stdin); if(c==EOF) exit(0); if(opt['u'] && c>='a' && c<='z') c+='A'-'a'; else if(opt['l'] && c>='A' && c<='Z') c+='a'-'A'; if(opt['s']) { if(c=='/') d=1; else if(c && c!='.') d=0; if((c&~127) || !safe[c] || (c=='.' && n && name[n-1]=='.') || (c=='/' && d)) c='_'; } name[n++]=c; if(!c) break; if(n==254) fatal("Name too long: %s",name); } if(opt['s']) { if(!n) name[1]=0,n=1; if(d) name[n-1]='_'; } size=fgetc(stdin)<<16; size|=fgetc(stdin)<<24; size|=fgetc(stdin); size|=fgetc(stdin)<<8; if(argc<3) { o=1; } else { o=0; for(n=2;n<argc;n++) { if(!strcmp(name,argv[n])) { o=1; if(opt['r'] && ++n<argc) strcpy(name,argv[n]); break; } else if(opt['w']) { for(c=d=0;;c++,d++) { if(argv[n][c]=='*') { d+=strlen(name)-strlen(argv[n]); if(d>=strlen(name) || d<c) break; } else if(argv[n][c]!=name[d] && argv[n][c]!='?') { break; } else if(!name[d]) { o=1; break; } } } if(opt['r']) n++; } } if(opt['d']) o=!o; } if(o && opt['t']) { puts(name); o=0; } if(o) { if(opt['x']) { fp=fopen(name,"w"); if(!fp) { perror(name); fatal("Cannot open file for output"); } } else { fp=stdout; if(!opt['o']) { fwrite(name,1,strlen(name)+1,stdout); putchar(size>>16); putchar(size>>24); putchar(size); putchar(size>>8); } } while(size--) fputc(fgetc(in),fp); if(opt['x']) fclose(fp); } else { while(size--) fgetc(in); } if(opt['c']) fclose(in); } int main(int Argc,char**Argv) { char*t; int a; argc=Argc; argv=Argv; if(argc>1) for(t=argv[1];*t;) opt[*t++&127]=1; if(opt['c']) { for(a=2;a<argc;a+=opt['r']+1) process_lump(a); } else { for(;;) process_lump(0); } return 0; }