From a25320e2fa316b9c9ce0b3720aba6b7a58ad283f Mon Sep 17 00:00:00 2001 From: Toni G Date: Wed, 13 Mar 2013 15:31:58 +0100 Subject: [PATCH] added Galt's patch --- examples/patch_unadf_2010_0209_Galt_Barber | 472 +++++++++++++++++++++ 1 file changed, 472 insertions(+) create mode 100644 examples/patch_unadf_2010_0209_Galt_Barber diff --git a/examples/patch_unadf_2010_0209_Galt_Barber b/examples/patch_unadf_2010_0209_Galt_Barber new file mode 100644 index 0000000..2d9c7eb --- /dev/null +++ b/examples/patch_unadf_2010_0209_Galt_Barber @@ -0,0 +1,472 @@ +--- unadf.c 2013-02-22 09:16:21.585508471 +0100 ++++ /var/tmp/unadf_2010_0209.c 2013-03-13 15:26:48.915232398 +0100 +@@ -29,6 +29,11 @@ + #include + #include + ++#include ++#include ++#include ++ ++ + #include "adflib.h" + + /* The portable way used to create a directory is to call the MKDIR command via the +@@ -65,6 +70,62 @@ + puts(" -d dir : extract to 'dir' directory"); + } + ++int nukeIllegalWindowsTrailingChars(char *filename, char *endMem) ++{ ++ int l = strlen(filename); ++ int i = l - 1; ++ char *j; ++ int count = 0; ++ while (filename[i] == ' ' || filename[i] == '.') { ++ for(j=filename+i; j < endMem; ++j) ++ *j = *(j+1); ++ --endMem; ++ ++count; ++ --i; ++ if (i == 0) { ++ fprintf(stderr, "unexpected error trimming illegal trailing chars \".\" and space from filename left nothing.\n"); ++ exit(1); ++ } ++ } ++ return count; ++ ++} ++ ++void setFileDateTime(char *filename, struct Entry* entry) ++{ ++ ++ struct tm t; ++ time_t t_of_day; ++ struct utimbuf tb; ++ ++ /* ++ Floor the year for windows to 1980. ++ This is because some users did not set their clock right ++ and the first possible Amiga year 1978 would appear frequently making ++ the file dates on early Amiga computers potentially less useful. ++ Windows (although not NTFS itself) barfs on dates with year less than 1980. ++ */ ++ if (entry->year < 1980) ++ entry->year = 1980; ++ ++ t.tm_year = entry->year - 1900; ++ t.tm_mon = entry->month - 1; ++ t.tm_mday = entry->days; ++ t.tm_hour = entry->hour; ++ t.tm_min = entry->mins; ++ t.tm_sec = entry->secs; ++ t.tm_isdst = -1; ++ ++ t_of_day = mktime(&t); ++ ++ memcpy (&tb.actime, &t_of_day, sizeof (time_t)); ++ memcpy (&tb.modtime, &t_of_day, sizeof (time_t)); ++ ++ if (utime(filename, &tb) != 0) ++ fprintf(stderr, "error calling utime on %s\n", filename); ++ ++} ++ + void printEnt(struct Volume *vol, struct Entry* entry, char *path, BOOL sect) + { + /* do not print the links entries, ADFlib do not support them yet properly */ +@@ -97,21 +158,26 @@ + + + void extractFile(struct Volume *vol, char* name, char* path, unsigned char *extbuf, +- BOOL pflag, BOOL qflag) ++ BOOL pflag, BOOL qflag, struct Entry * entry) + { + struct File *file; + FILE* out; + long n; + char *filename; ++ char *fixedFileName = malloc(strlen(name)+1); ++ ++ strcpy(fixedFileName, name); ++ ++ nukeIllegalWindowsTrailingChars(fixedFileName, fixedFileName+strlen(fixedFileName)); + + filename = NULL; + if (pflag) + out = stdout; + else { + if (strlen(path)>0) { +- filename=(char*)malloc(sizeof(char)* (strlen(path)+1+strlen(name)+1) ); ++ filename=(char*)malloc(sizeof(char)* (strlen(path)+1+strlen(fixedFileName)+1) ); + if (!filename) return; +- sprintf(filename,"%s%c%s",path,DIRSEP,name); ++ sprintf(filename,"%s%c%s",path,DIRSEP,fixedFileName); + out = fopen(filename, "wb"); + } + else +@@ -130,16 +196,27 @@ + if (n>0) + fwrite(extbuf, sizeof(unsigned char), n, out); + +- if (!pflag) ++ adfCloseFile(file); ++ ++ if (!pflag) { ++ + fclose(out); + +- adfCloseFile(file); ++ printf("%4d/%02d/%02d %2d:%02d:%02d ",entry->year, entry->month, entry->days, ++ entry->hour, entry->mins, entry->secs); ++ ++ setFileDateTime(filename, entry); ++ ++ } ++ + + if (!qflag) { + if (filename!=NULL) + printf("x - %s\n", filename); + else + printf("x - %s\n", name); ++ ++ + } + + if (filename!=NULL) +@@ -150,34 +227,47 @@ + void extractTree(struct Volume *vol, struct List* tree, char *path, unsigned char *extbuf, + BOOL pflag, BOOL qflag) + { +- struct Entry* entry; ++ struct Entry* entry; + char *buf; + char sysbuf[200]; + + while(tree) { + entry = (struct Entry*)tree->content; + if (entry->type==ST_DIR) { ++ char mysep[2]; + buf = NULL; ++ if (!qflag && !pflag) { ++ printf("%4d/%02d/%02d %2d:%02d:%02d ", ++ entry->year, entry->month, entry->days, ++ entry->hour, entry->mins, entry->secs); ++ } + if (strlen(path)>0) { +- buf=(char*)malloc(strlen(path)+1+strlen(entry->name)+1); +- if (!buf) return; +- sprintf(buf,"%s%c%s",path,DIRSEP,entry->name); +- sprintf(sysbuf,"%s %s",MKDIR,buf); +- if (!qflag) printf("x - %s%c\n",buf,DIRSEP); ++ mysep[0] = DIRSEP; ++ mysep[1] = 0; + } + else { +- sprintf(sysbuf,"%s %s",MKDIR,entry->name); +- if (!qflag) printf("x - %s%c\n",entry->name,DIRSEP); ++ mysep[0] = 0; + } + +- if (!pflag) system(sysbuf); ++ buf=(char*)malloc(strlen(path)+strlen(mysep)+strlen(entry->name)+1); ++ if (!buf) return; ++ sprintf(buf,"%s%s%s",path,mysep,entry->name); ++ ++ ++ nukeIllegalWindowsTrailingChars(buf, buf+strlen(buf)); + +- if (tree->subdir!=NULL) { ++ ++ /* use double quotes around argument for paths with embedded spaces */ ++ sprintf(sysbuf,"%s \"%s\"",MKDIR,buf); ++ if (!qflag) printf("x - %s%s\n",buf,mysep); ++ ++ if (!pflag) ++ system(sysbuf); ++ ++ ++ if (tree->subdir!=NULL) { + if (adfChangeDir(vol,entry->name)==RC_OK) { +- if (buf!=NULL) +- extractTree(vol,tree->subdir,buf,extbuf, pflag, qflag); +- else +- extractTree(vol,tree->subdir,entry->name,extbuf, pflag, qflag); ++ extractTree(vol,tree->subdir,buf,extbuf, pflag, qflag); + adfParentDir(vol); + } + else { +@@ -188,17 +278,22 @@ + } + } + ++ if (!pflag) { ++ setFileDateTime(buf, entry); ++ } ++ + if (buf!=NULL) + free(buf); + } + else if (entry->type==ST_FILE) { +- extractFile(vol,entry->name,path,extbuf, pflag, qflag); ++ extractFile(vol,entry->name,path,extbuf, pflag, qflag, entry); + } + tree = tree->next; + } + } + + ++ + void printTree(struct Volume *vol, struct List* tree, char* path, BOOL sect) + { + char *buf; +@@ -286,83 +381,166 @@ + + } + ++struct Entry* findEntryInDir(struct Volume *vol, char *filename, struct List** plist) { ++ struct List *list, *cell; ++ cell = list = adfGetDirEnt(vol,vol->curDirPtr); ++ *plist = list; ++ while(cell) { ++ struct Entry *entry = (struct Entry*)cell->content; ++ if (strcmp(entry->name, filename)==0) ++ return entry; ++ cell = cell->next; ++ } ++ return NULL; ++} ++ ++struct saveParentDir { ++ struct saveParentDir *next; ++ char *fullname; ++ struct Entry* entry; ++ struct List* list; ++}; ++ + + void processFile(struct Volume *vol, char* name, char* path, unsigned char *extbuf, + BOOL pflag, BOOL qflag) + { +- char *sepptr, *cdstr, *fullname, *filename; +- char *bigstr; ++ char *sepptr, *cdstr, *fullname, *filename; ++ char *bigstr = NULL; + FILE *tfile; ++ struct List *list; ++ struct Entry* entry; ++ struct saveParentDir* spdhead = NULL, *n; ++ char mysep[2]; ++ int bigsize; ++ char *endMem; ++ int trimCount; + + adfToRootDir(vol); + + sepptr = strchr(name, '/'); + if (sepptr==NULL) { +- extractFile(vol, name, path, extbuf, pflag, qflag); ++ filename = name; ++ fullname = path; + } + else { + /* the all-in-one string : to call system(), to find the filename, the convert dir sep char ... */ +- bigstr=(char*)malloc(strlen(MKDIR)+1+strlen(path)+1+strlen(name)+1); ++ bigsize=strlen(MKDIR)+1+1+strlen(path)+1+strlen(name)+1+1; // includes double-quotes around MKDIR arg ++ bigstr=(char*)malloc(bigsize); + if (!bigstr) { fprintf(stderr,"processFile : malloc"); return; } + ++ if (strlen(path)>0) { ++ mysep[0] = DIRSEP; ++ mysep[1] = 0; ++ } ++ else { ++ mysep[0] = 0; ++ } ++ + /* to build to extract path */ +- if (strlen(path)>0) { +- sprintf(bigstr,"%s %s%c%s",MKDIR,path,DIRSEP,name); +- cdstr = bigstr+strlen(MKDIR)+1+strlen(path)+1; +- } +- else { +- sprintf(bigstr,"%s %s",MKDIR,name); +- cdstr = bigstr+strlen(MKDIR)+1; +- } ++ /* use double quotes around argument for paths with embedded spaces */ ++ sprintf(bigstr,"%s \"%s%s%s",MKDIR,path,mysep,name); ++ bigsize = strlen(bigstr); ++ endMem = bigstr+bigsize; ++ cdstr = bigstr+strlen(MKDIR)+1+strlen(path)+strlen(mysep)+1; ++ + /* the directory in which the file will be extracted */ +- fullname = bigstr+strlen(MKDIR)+1; ++ fullname = bigstr+strlen(MKDIR)+1+1; + + /* finds the filename, and separates it from the path */ + filename = strrchr(bigstr,'/')+1; + filename[-1]='\0'; + + sepptr = cdstr; +- /* find the end of the first dir to create */ +- while(sepptr[0]!='/' && sepptr[0]!='\0') +- sepptr++; + +- while(strlen(cdstr)>0) { ++ BOOL found = TRUE; ++ while(found) { ++ /* find the end of the first dir to create */ ++ while(sepptr[0]!='/' && sepptr[0]!='\0') ++ sepptr++; + if (sepptr[0]=='/') { /* not the last one */ + sepptr[0]='\0'; +- if (adfChangeDir(vol,cdstr)!=RC_OK) +- return; +- tfile = fopen(fullname,"r"); /* the only portable way to test if the dir exists */ +- if (tfile==NULL) { /* does't exist : create it */ +- if (!pflag) system(bigstr); +- if (!qflag) printf("x - %s%c\n",fullname,DIRSEP); +- } +- else +- fclose(tfile); +- sepptr[0] = DIRSEP; /* converts the '/' to '/' or '\' */ +- cdstr = sepptr+1; /* next beginning of the next dir to create */ +- /* to find the end of the next dir */ +- sepptr++; +- while(sepptr[0]!='/' && sepptr[0]!='\0') +- sepptr++; +- } +- else { /* the last one */ +- if (adfChangeDir(vol,cdstr)!=RC_OK) +- return; +- tfile = fopen(fullname,"r"); +- if (tfile==NULL) { +- if (!pflag) system(bigstr); +- if (!qflag) printf("x - %s%c\n",fullname,DIRSEP); +- } +- else +- fclose(tfile); +- cdstr = cdstr+strlen(cdstr); /* at the end, ends the while loop */ +- } ++ } ++ else ++ found = FALSE; ++ ++ ++ entry = findEntryInDir(vol, cdstr, &list); ++ if (!entry) { ++ fprintf(stderr, " subdir %s not found in dir list findEntryInDir\n", cdstr); ++ return; ++ } ++ ++ printf("%4d/%02d/%02d %2d:%02d:%02d ",entry->year, entry->month, entry->days, ++ entry->hour, entry->mins, entry->secs); ++ ++ if (adfChangeDir(vol,cdstr)!=RC_OK) ++ { ++ fprintf(stderr, " adfChangDir to subdir %s failed.\n", cdstr); ++ return; ++ } ++ ++ trimCount = nukeIllegalWindowsTrailingChars(cdstr, endMem); ++ endMem -= trimCount; ++ ++ n = spdhead; ++ spdhead = malloc(sizeof(struct saveParentDir)); ++ spdhead->next = n; ++ spdhead->fullname = malloc(strlen(fullname)+1); ++ strcpy(spdhead->fullname, fullname); ++ spdhead->entry = entry; ++ spdhead->list = list; ++ ++ tfile = fopen(fullname,"r"); /* the only portable way to test if the dir exists */ ++ if (tfile==NULL) { /* does't exist : create it */ ++ if (!pflag) { ++ int bsl = strlen(bigstr); ++ char saveEos = bigstr[bsl+1]; ++ /* compensate for middle-string parsing */ ++ bigstr[bsl] = '"'; ++ bigstr[bsl+1] = 0; ++ system(bigstr); ++ bigstr[bsl] = 0; ++ bigstr[bsl+1] = saveEos; ++ } ++ if (!qflag) ++ printf("x - %s%c\n",fullname,DIRSEP); ++ } ++ else ++ fclose(tfile); ++ ++ if (found) { ++ sepptr[0] = DIRSEP; /* converts the '/' to '/' or '\' */ ++ cdstr = ++sepptr; /* next beginning of the next dir to create */ ++ } + } +- extractFile(vol, filename, fullname, extbuf, pflag, qflag); ++ } ++ entry = findEntryInDir(vol, filename, &list); ++ if (entry) { ++ if (entry->type==ST_FILE) ++ extractFile(vol, filename, fullname, extbuf, pflag, qflag, entry); ++ else ++ fprintf(stderr, "file %s found but type not ST_FILE.\n", filename); ++ } ++ else { ++ fprintf(stderr, "file %s not found.\n", filename); ++ } ++ ++ adfFreeDirList(list); + +- free(bigstr); ++ while(spdhead) { ++ n = spdhead; ++ if (n->entry->type==ST_DIR) ++ setFileDateTime(n->fullname, n->entry); ++ free(n->fullname); ++ adfFreeDirList(n->list); ++ spdhead = spdhead->next; ++ free(n); + } + ++ if (bigstr) ++ free(bigstr); ++ + + } + +@@ -397,9 +575,12 @@ + files = rtfiles = NULL; + volNum = 0; + +- fprintf(stderr,"unADF v%s : a unzip like for .ADF files, powered by ADFlib (v%s - %s)\n\n", ++ fprintf(stderr,"\n\nunADF v%s : a unzip like for .ADF files, powered by ADFlib (v%s - %s)\n\n", + UNADF_VERSION, adfGetVersionNumber(),adfGetVersionDate()); + ++ fprintf(stderr,"Note: for windows compatibility, during extraction, dates with years before 1980 are set to 1980,\n"); ++ fprintf(stderr," and directory and file names ending in \" \" or \".\" are trimmed.\n\n"); ++ + /* parse options */ + i=1; + while(i