libclammspack/test/cabd_md5.c
d3699d57
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <mspack.h>
 #include <sys/stat.h>
 #include <dirent.h>
 
 #include <md5_fh.h>
 #include <error.h>
 
 /**
  * Matches a cabinet's filename case-insensitively in the filesystem and
  * returns the case-correct form.
  *
  * @param origcab if this is non-NULL, the pathname part of this filename
  *                will be extracted, and the search will be conducted in
  *                that directory.
  * @param cabname the internal CAB filename to search for.
  * @return a copy of the full, case-correct filename of the given cabinet
  *         filename, or NULL if the specified filename does not exist on disk.
  */
 static char *find_cabinet_file(char *origcab, char *cabname) {
     struct dirent *entry;
     struct stat st_buf;
     int found = 0, len;
     char *tail, *cab;
     DIR *dir;
 
     /* ensure we have a cabinet name at all */
     if (!cabname || !cabname[0]) return NULL;
 
     /* find if there's a directory path in the origcab */
     tail = origcab ? strrchr(origcab, '/') : NULL;
     len = (tail - origcab) + 1;
 
     /* allocate memory for our copy */
     if (!(cab = (char *) malloc((tail ? len : 2) + strlen(cabname) + 1))) return NULL;
 
     /* add the directory path from the original cabinet name, or "." */
     if (tail) memcpy(cab, origcab, (size_t) len);
     else      cab[0]='.', cab[1]='/', len=2;
     cab[len] = '\0';
 
     /* try accessing the cabinet with its current name (case-sensitive) */
     strcpy(&cab[len], cabname);
     if (stat(cab, &st_buf) == 0) {
cafa0bf3
         found = 1;
d3699d57
     }
     else {
cafa0bf3
         /* cabinet was not found, look for it in the current dir */
         cab[len] = '\0';
         if ((dir = opendir(cab))) {
             while ((entry = readdir(dir))) {
                 if (strcasecmp(cabname, entry->d_name) == 0) {
                     strcat(cab, entry->d_name);
                     found = (stat(cab, &st_buf) == 0);
                     break;
                 }
             }
             closedir(dir);
         }
d3699d57
     }
 
     if (!found || !S_ISREG(st_buf.st_mode)) {
cafa0bf3
         /* cabinet not found, or not a regular file */
         free(cab);
         cab = NULL;
d3699d57
     }
 
     return cab;
 }
 
 
 int main(int argc, char *argv[]) {
     struct mscab_decompressor *cabd;
     struct mscabd_cabinet *cab, *c, *c2;
     struct mscabd_file *file;
     char *cabname, *newname;
     int err;
 
     setbuf(stdout, NULL);
     setbuf(stderr, NULL);
 
     /* if self-test reveals an error */
     MSPACK_SYS_SELFTEST(err);
     if (err) return 1;
 
     if (!(cabd = mspack_create_cab_decompressor(&read_files_write_md5))) {
cafa0bf3
         fprintf(stderr, "can't make decompressor\n");
         return 1;
d3699d57
     }
 
     for (argv++; (cabname = *argv); argv++) {
cafa0bf3
         printf("*** %s\n", cabname);
 
         if (!(cab = cabd->open(cabd, cabname))) {
             fprintf(stderr, "cab open error: %s\n", ERROR(cabd));
             continue;
         }
 
         /* prepend any spanning cabinets */
         for (c = cab; c && (c->flags & MSCAB_HDR_PREVCAB); c = c->prevcab) {
             if (!(newname = find_cabinet_file(cabname, c->prevname))) {
                 fprintf(stderr, "%s: can't find \"%s\" to prepend\n",
                         cabname, c->prevname);
                 break;
             }
             if (!(c2 = cabd->open(cabd, newname))) {
                 fprintf(stderr, "%s: error opening \"%s\" for prepend: %s\n",
                         cabname, newname, ERROR(cabd));
                 break;
             }
             if (cabd->prepend(cabd, c, c2) != MSPACK_ERR_OK) {
                 fprintf(stderr, "%s: error prepending \"%s\": %s\n",
                         cabname, newname, ERROR(cabd));
                 break;
             }
         }
 
         /* append any spanning cabinets */
         for (c = cab; c && (c->flags & MSCAB_HDR_NEXTCAB); c = c->nextcab) {
             if (!(newname = find_cabinet_file(cabname, c->nextname))) {
                 fprintf(stderr, "%s: can't find \"%s\" to append\n",
                         cabname, c->nextname);
                 break;
             }
             if (!(c2 = cabd->open(cabd, newname))) {
                 fprintf(stderr, "%s: error opening \"%s\" for append: %s\n",
                         cabname, newname, ERROR(cabd));
                 break;
             }
             if (cabd->append(cabd, c, c2) != MSPACK_ERR_OK) {
                 fprintf(stderr, "%s: error appending \"%s\": %s\n",
                         cabname, newname, ERROR(cabd));
                 break;
             }
         }
 
         /* extract files */
         for (file = cab->files; file; file = file->next ) {
             if (cabd->extract(cabd, file, NULL) == MSPACK_ERR_OK) {
                 printf("%s  %s\n", md5_string, file->filename);
             }
             else {
                 fprintf(stderr, "%s: error extracting \"%s\": %s\n",
                         cabname, file->filename, ERROR(cabd));
             }
         }
 
         /* free all resources */
         for (c2 = cab->prevcab; c2; c2 = c2->prevcab) free((void*)c2->filename);
         for (c2 = cab->nextcab; c2; c2 = c2->nextcab) free((void*)c2->filename);
         cabd->close(cabd, cab);
d3699d57
     }
     mspack_destroy_cab_decompressor(cabd);
     return 0;
 }