home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / macutils.lzh / MACUTILS / FILEIO / rdfile.c < prev    next >
C/C++ Source or Header  |  1996-02-01  |  27KB  |  1,032 lines

  1. #include <stdio.h>
  2. #ifdef TYPES_H
  3. #ifndef OSK
  4. #include <sys/types.h>
  5. #endif
  6. #endif /* TYPES_H */
  7.  
  8. #ifndef OSK
  9. #include <sys/stat.h>
  10. #else
  11. #include "/dd/blarsdefs/sys/stat.h"
  12. #endif
  13.  
  14.  
  15. #include "machdr.h"
  16. #include "rdfile.h"
  17. #include "rdfileopt.h"
  18.  
  19. #ifndef OSK
  20. #ifndef DIRENT_H
  21. #include <sys/dir.h>
  22. #define dirstruct direct
  23. #else /* DIRENT_H */
  24. #include <dirent.h>
  25. #define dirstruct dirent
  26. #endif /* DIRENT_H */
  27. #else
  28. #include <dir.h>
  29. #define dirstruct direct
  30. #endif
  31.  
  32. #ifndef OSK
  33. #include "../util/curtime.h"
  34. #else
  35. #define TIMEDIFF 0x7c25b080
  36. #endif
  37.  
  38. #include "../util/masks.h"
  39. #include "../util/util.h"
  40.  
  41. #ifdef AUFSPLUS
  42. #define AUFS
  43. #endif /* AUFSPLUS */
  44. #ifdef AUFS
  45. #define APPLESHARE
  46. #endif /* AUFS */
  47. #ifdef APPLEDOUBLE
  48. #define APPLESHARE
  49. #endif /* APPLEDOUBLE */
  50.  
  51. #define NOTFOUND    0
  52. #define ISFILE        1
  53. #define    INFOFILE    2
  54. #define INFOEXT        3
  55. #define    SKIPFILE    4
  56. #define    MACBINARY    5
  57. #define    DIRECTORY    6
  58. #ifdef APPLESHARE
  59. #define    SHAREFILE    7
  60. #endif /* APPLESHARE */
  61.  
  62. #define DATA_FORMAT    1
  63. #define RSRC_FORMAT    2
  64. #define UNIX_FORMAT    3
  65.  
  66. extern char *malloc();
  67. extern char *realloc();
  68. extern char *strcpy();
  69. extern char *strncpy();
  70. extern char *strcat();
  71. extern void exit();
  72.  
  73. static void check_files();
  74. static void read_file();
  75. static void enter_dir();
  76. static void exit_dir();
  77. static int get_stdin_file();
  78.  
  79. char file_info[INFOBYTES];
  80. char *data_fork, *rsrc_fork;
  81. int data_size, rsrc_size;
  82. static int max_data_size, max_rsrc_size;
  83.  
  84. typedef struct filelist {
  85.     int nfiles;
  86.     char **files;
  87.     int *kind;
  88.     struct filelist *previous;
  89.     int current;
  90. #ifdef APPLESHARE
  91.     int shared_dir;
  92. #endif /* APPLESHARE */
  93. } filelist;
  94.  
  95. static int data_only;
  96. static int no_recurse;
  97. static int read_stdin;
  98. static filelist global_files;
  99. static filelist *current_files;
  100. static char f_auth[5];
  101. static char f_type[5];
  102. static char f_name[] = ".foldername";
  103. #ifdef APPLESHARE
  104. #ifdef AUFS
  105. #include "aufs.h"
  106. static char infodir[] = ".finderinfo";
  107. static char rsrcdir[] = ".resource";
  108. static void read_aufs_info();
  109. #endif /* AUFS */
  110. #ifdef APPLEDOUBLE
  111. #include "appledouble.h"
  112. static char infodir[] = ".AppleDouble";
  113. static void read_appledouble_info();
  114. #endif /* APPLEDOUBLE */
  115. #endif /* APPLESHARE */
  116. static char filename[255];
  117. static int filekind;
  118.  
  119. void setup(argc, argv)
  120. int argc;
  121. char **argv;
  122. {
  123.     if(argc == 0) {
  124.     read_stdin = 1;
  125.     } else {
  126.     read_stdin = 0;
  127.     global_files.previous = NULL;
  128.     global_files.nfiles = argc;
  129.     global_files.files = argv;
  130.     global_files.current = 0;
  131.     current_files = &global_files;
  132.     check_files(1);
  133.     }
  134. }
  135.  
  136. static void check_files(initial)
  137. int initial;
  138. {
  139.     struct stat stbuf;
  140.     int i, j, n;
  141.     char filename[255], filename1[255];
  142.  
  143.     /* Check the method to read the file */
  144.     current_files->current = 0;
  145.     /* Set initially to NOTFOUND or DIRECTORY */
  146.     n = current_files->nfiles;
  147.     current_files->kind = (int *)malloc((unsigned)n * sizeof(int));
  148.     if(current_files->kind == NULL) {
  149.     (void)fprintf(stderr, "Insufficient memory\n");
  150.     exit(1);
  151.     }
  152.     for(i = 0; i < n; i++) {
  153.     current_files->kind[i] = NOTFOUND;
  154.     if(stat(current_files->files[i], &stbuf) >= 0) {
  155.         if((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  156.         /* We found a directory */
  157.         current_files->kind[i] = DIRECTORY;
  158.         continue;
  159.         }
  160.         current_files->kind[i] = ISFILE;
  161.     }
  162.     }
  163.     /* That is enough for data_only mode */
  164.     if(data_only) {
  165.     return;
  166.     }
  167. #ifdef APPLESHARE
  168.     /* First check whether we are in a folder on a shared volume */
  169.     i = 1;
  170. #ifdef AUFS
  171.     if(stat(rsrcdir,&stbuf) < 0) {
  172.     i = 0;
  173.     } else {
  174.     if((stbuf.st_mode & S_IFMT) != S_IFDIR) {
  175.         i = 0;
  176.     }
  177.     }
  178.     if(stat(infodir,&stbuf) < 0) {
  179.     i = 0;
  180.     } else {
  181.     if((stbuf.st_mode & S_IFMT) != S_IFDIR) {
  182.         i = 0;
  183.     }
  184.     }
  185. #endif /* AUFS */
  186. #ifdef APPLEDOUBLE
  187.     if(stat(infodir,&stbuf) < 0) {
  188.     i = 0;
  189.     } else {
  190.     if((stbuf.st_mode & S_IFMT) != S_IFDIR) {
  191.         i = 0;
  192.     }
  193.     }
  194. #endif /* APPLEDOUBLE */
  195.     current_files->shared_dir = i;
  196. #endif /* APPLESHARE */
  197.     for(i = 0; i < n; i++) {
  198.     if(current_files->kind[i] == NOTFOUND) {
  199.         j = 0;
  200.     } else if(current_files->kind[i] == ISFILE) {
  201.         /* Check whether the file is special */
  202. #ifdef APPLESHARE
  203.         if(!current_files->shared_dir &&
  204.            !strcmp(current_files->files[i], f_name)) {
  205.         current_files->kind[i] = SKIPFILE;
  206.         continue;
  207.         }
  208. #else /* APPLESHARE */
  209.         if(!strcmp(current_files->files[i], f_name)) {
  210.         current_files->kind[i] = SKIPFILE;
  211.         continue;
  212.         }
  213. #endif /* APPLESHARE */
  214.         j = 1;
  215.     } else if(current_files->kind[i] == SKIPFILE) {
  216.         continue;
  217.     } else if(!initial) { /* DIRECTORY */
  218.         /* Check whether the directory is special */
  219.         if(!strcmp(current_files->files[i], ".") ||
  220.            !strcmp(current_files->files[i], "..")) {
  221.         current_files->kind[i] = SKIPFILE;
  222.         }
  223. #ifdef APPLESHARE
  224. #ifdef AUFS
  225.         if(current_files->shared_dir &&
  226.            (!strcmp(current_files->files[i], infodir) ||
  227.         !strcmp(current_files->files[i], rsrcdir))) {
  228.         current_files->kind[i] = SKIPFILE;
  229.         }
  230. #endif /* AUFS */
  231. #ifdef APPLEDOUBLE
  232.         if(current_files->shared_dir &&
  233.            !strcmp(current_files->files[i], infodir)) {
  234.         current_files->kind[i] = SKIPFILE;
  235.         }
  236. #endif /* APPLEDOUBLE */
  237. #endif /* APPLESHARE */
  238.         continue;
  239.     } else { /* Take all directories from command line! */
  240.         continue;
  241.     }
  242. #ifdef APPLESHARE
  243.     /* Check whether file is in shared format */
  244.     if(j & current_files->shared_dir) {
  245.         j = 0;
  246.         filename[0] = 0;
  247.         (void)strcat(filename, infodir);
  248.         (void)strcat(filename, "/");
  249.         (void)strcat(filename, current_files->files[i]);
  250.         /* There ought to be an associated file in the info direcory */
  251.         if(stat(filename, &stbuf) >= 0) {
  252.         current_files->kind[i] = SHAREFILE;
  253.         continue;
  254.         }
  255.     }
  256. #endif /* APPLESHARE */
  257.     /* If file not found check for the same with .info extension */
  258.     if(!j) {
  259.         filename[0] = 0;
  260.         (void)strcat(filename, current_files->files[i]);
  261.         (void)strcat(filename, ".info");
  262.         /* Found a .info file, else no such file found */
  263.         if(stat(filename, &stbuf) >= 0) {
  264.         current_files->kind[i] = INFOEXT;
  265.         }
  266.         continue;
  267.     }
  268.     /* Now we found the file.  Check first whether the name ends with
  269.        .info */
  270.     j = strlen(current_files->files[i]) - 5;
  271.     if(!strncmp(current_files->files[i] + j, ".info", 5)) {
  272.         /* This is a .info file.  Set as INFOFILE */
  273.         current_files->kind[i] = INFOFILE;
  274.         /* Now remove from list of files the same with .data or .rsrc
  275.            extension */
  276.         filename[0] = 0;
  277.         (void)strcat(filename, current_files->files[i]);
  278.         filename[j] = 0;
  279.         (void)strcpy(filename1, filename);
  280.         (void)strcat(filename, ".data");
  281.         (void)strcat(filename1, ".rsrc");
  282.         for(j = i + 1; j < n; j++) {
  283.         if(!strcmp(filename, current_files->files[j])) {
  284.             /* Associated .data file */
  285.             current_files->kind[j] = SKIPFILE;
  286.             continue;
  287.         }
  288.         if(!strcmp(filename1, current_files->files[j])) {
  289.             /* Associated .rsrc file */
  290.             current_files->kind[j] = SKIPFILE;
  291.         }
  292.         }
  293.         continue;
  294.     }
  295.     if(!strncmp(current_files->files[i] + j, ".data", 5) ||
  296.        !strncmp(current_files->files[i] + j, ".rsrc", 5)) {
  297.         /* .data or .rsrc file found.  Check whether there is an
  298.            associated .info file in the filelist */
  299.         filename[0] = 0;
  300.         (void)strcat(filename, current_files->files[i]);
  301.         filename[j] = 0;
  302.         (void)strcat(filename, ".info");
  303.         for(j = i + 1; j < n; j++) {
  304.         if(!strcmp(filename, current_files->files[j])) {
  305.             /* Found an associated .info file! */
  306.             current_files->kind[i] = SKIPFILE;
  307.             break;
  308.         }
  309.         }
  310.         if(j < n) {
  311.         continue;
  312.         }
  313.     }
  314.     /* Finally nothing special */
  315.     current_files->kind[i] = MACBINARY;
  316.     }
  317. }
  318.  
  319. int nextfile()
  320. {
  321.     int i;
  322.  
  323.     if(read_stdin) {
  324.     return get_stdin_file();
  325.     }
  326.     i = current_files->current;
  327. again:
  328.     if(i == current_files->nfiles) {
  329.     if(current_files->previous == NULL) {
  330.         return ISATEND;
  331.     } else {
  332.         exit_dir();
  333.         current_files->current++;
  334.         return ENDDIR;
  335.     }
  336.     }
  337.     filename[0] = 0;
  338.     (void)strcat(filename, current_files->files[i]);
  339.     filekind = current_files->kind[i];
  340.     switch(filekind) {
  341.     case DIRECTORY:
  342.     if(no_recurse) {
  343.         (void)fprintf(stderr, "Directory %s skipped.\n", filename);
  344.         i++;
  345.         current_files->current = i;
  346.         goto again;
  347.     }
  348.     enter_dir();
  349.     return ISDIR;
  350.     case SKIPFILE:
  351.     i++;
  352.     current_files->current = i;
  353.     goto again;
  354.     case NOTFOUND:
  355.     (void)fprintf(stderr, "File %s not found.\n", filename);
  356.     exit(1);
  357.     default:
  358.     read_file();
  359.     current_files->current = i + 1;
  360.     return ISFILE;
  361.     }
  362. }
  363.  
  364. static void read_file()
  365. {
  366.     FILE *fd;
  367.     int c, j, lname, skip;
  368.     struct stat stbuf;
  369. #ifdef APPLESHARE
  370.     char filename1[255];
  371. #endif /* APPLESHARE */
  372.  
  373.     switch(filekind) {
  374.     case ISFILE:
  375.     if(stat(filename, &stbuf) < 0) {
  376.         (void)fprintf(stderr, "Cannot stat file %s\n", filename);
  377.         exit(1);
  378.     }
  379.     for(j = 0; j < INFOBYTES; j++) {
  380.         file_info[j] = 0;
  381.     }
  382.     (void)strcpy(file_info + I_NAMEOFF + 1, filename);
  383.     file_info[I_NAMEOFF] = strlen(filename);
  384.     put4(file_info + I_CTIMOFF, (unsigned long)stbuf.st_ctime + TIMEDIFF);
  385.     put4(file_info + I_MTIMOFF, (unsigned long)stbuf.st_mtime + TIMEDIFF);
  386.     if(data_only == RSRC_FORMAT) {
  387.         rsrc_size = stbuf.st_size;
  388.         data_size = 0;
  389.         if(rsrc_size > max_rsrc_size) {
  390.         if(rsrc_fork == NULL) {
  391.             rsrc_fork = malloc((unsigned)rsrc_size);
  392.         } else {
  393.             rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  394.         }
  395.         max_rsrc_size = rsrc_size;
  396.         }
  397.         if(f_type[0] == 0) {
  398.         (void)strncpy(file_info + I_TYPEOFF, "RSRC", 4);
  399.         } else {
  400.         (void)strncpy(file_info + I_TYPEOFF, f_type, 4);
  401.         }
  402.         if(f_auth[0] == 0) {
  403.         (void)strncpy(file_info + I_AUTHOFF, "RSED", 4);
  404.         } else {
  405.         (void)strncpy(file_info + I_AUTHOFF, f_auth, 4);
  406.         }
  407.         put4(file_info + I_RLENOFF, (unsigned long)rsrc_size);
  408.         if((fd = fopen(filename, "r")) == NULL) {
  409.         (void)fprintf(stderr, "Cannot open file %s\n", filename);
  410.         exit(1);
  411.         }
  412.         if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) {
  413.         (void)fprintf(stderr, "Short file %s\n", filename);
  414.         exit(1);
  415.         }
  416.         (void)fclose(fd);
  417.     } else {
  418.         data_size = stbuf.st_size;
  419.         rsrc_size = 0;
  420.         if(data_size > max_data_size) {
  421.         if(data_fork == NULL) {
  422.             data_fork = malloc((unsigned)data_size);
  423.         } else {
  424.             data_fork = realloc(data_fork, (unsigned)data_size);
  425.         }
  426.         max_data_size = data_size;
  427.         }
  428.         if(f_type[0] == 0) {
  429.         (void)strncpy(file_info + I_TYPEOFF, "TEXT", 4);
  430.         } else {
  431.         (void)strncpy(file_info + I_TYPEOFF, f_type, 4);
  432.         }
  433.         if(f_auth[0] == 0) {
  434.         (void)strncpy(file_info + I_AUTHOFF, "MACA", 4);
  435.         } else {
  436.         (void)strncpy(file_info + I_AUTHOFF, f_auth, 4);
  437.         }
  438.         put4(file_info + I_DLENOFF, (unsigned long)data_size);
  439.         if((fd = fopen(filename, "r")) == NULL) {
  440.         (void)fprintf(stderr, "Cannot open file %s\n", filename);
  441.         exit(1);
  442.         }
  443.         if(fread(data_fork, 1, data_size, fd) != data_size) {
  444.         (void)fprintf(stderr, "Short file %s\n", filename);
  445.         exit(1);
  446.         }
  447.         (void)fclose(fd);
  448.         if(data_only == UNIX_FORMAT) {
  449.         for(j = 0; j < data_size; j++) {
  450.             c = data_fork[j];
  451.             if(c == '\012' || c == '\015') {
  452.             data_fork[j] = '\027' -c;
  453.              }
  454.          }
  455.          }
  456.     }
  457.     break;
  458.     case INFOEXT:
  459.     (void)strcat(filename, ".info");
  460.     case INFOFILE:
  461.     lname = strlen(filename) - 5;
  462.     if((fd = fopen(filename, "r")) == NULL) {
  463.         (void)fprintf(stderr, "Cannot open file %s\n", filename);
  464.         exit(1);
  465.     }
  466.     if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) {
  467.         (void)fprintf(stderr, "Cannot read info header %s\n", filename);
  468.     }
  469.     (void)fclose(fd);
  470.     data_size = get4(file_info + I_DLENOFF);
  471.     rsrc_size = get4(file_info + I_RLENOFF);
  472.     if(data_size > max_data_size) {
  473.         if(data_fork == NULL) {
  474.         data_fork = malloc((unsigned)data_size);
  475.         } else {
  476.         data_fork = realloc(data_fork, (unsigned)data_size);
  477.         }
  478.         max_data_size = data_size;
  479.     }
  480.     if(rsrc_size > max_rsrc_size) {
  481.         if(rsrc_fork == NULL) {
  482.         rsrc_fork = malloc((unsigned)rsrc_size);
  483.         } else {
  484.         rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  485.         }
  486.         max_rsrc_size = rsrc_size;
  487.     }
  488.     if(data_size != 0) {
  489.         filename[lname] = 0;
  490.         (void)strcat(filename, ".data");
  491.         if((fd = fopen(filename, "r")) == NULL) {
  492.         (void)fprintf(stderr, "Cannot open data fork %s\n", filename);
  493.         exit(1);
  494.         }
  495.         if(fread(data_fork, 1, data_size, fd) != data_size) {
  496.         (void)fprintf(stderr, "Premature EOF on %s\n", filename);
  497.         }
  498.         (void)fclose(fd);
  499.     }
  500.     if(rsrc_size != 0) {
  501.         filename[lname] = 0;
  502.         (void)strcat(filename, ".rsrc");
  503.         if((fd = fopen(filename, "r")) == NULL) {
  504.         (void)fprintf(stderr, "Cannot open rsrc fork %s\n", filename);
  505.         exit(1);
  506.         }
  507.         if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) {
  508.         (void)fprintf(stderr, "Premature EOF on %s\n", filename);
  509.         }
  510.         (void)fclose(fd);
  511.     }
  512.     break;
  513.     case MACBINARY:
  514.     if((fd = fopen(filename, "r")) == NULL) {
  515.         (void)fprintf(stderr, "Cannot open file %s\n", filename);
  516.         exit(1);
  517.     }
  518.     if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) {
  519.         (void)fprintf(stderr, "Short file %s\n", filename);
  520.         exit(1);
  521.     }
  522.     if(file_info[0] != 0) {
  523.         (void)fprintf(stderr, "File is not MacBinary: %s\n", filename);
  524.         exit(1);
  525.     }
  526.     data_size = get4(file_info + I_DLENOFF);
  527.     rsrc_size = get4(file_info + I_RLENOFF);
  528.     if(file_info[I_LOCKOFF] & 1) {
  529.         file_info[I_FLAGOFF + 1] = PROTCT_MASK;
  530.         file_info[I_LOCKOFF] &= ~1;
  531.     }
  532.     if(data_size != 0) {
  533.         if(data_size > max_data_size) {
  534.         if(data_fork == NULL) {
  535.             data_fork = malloc((unsigned)data_size);
  536.         } else {
  537.             data_fork = realloc(data_fork, (unsigned)data_size);
  538.         }
  539.         max_data_size = data_size;
  540.         }
  541.         if(fread(data_fork, 1, data_size, fd) != data_size) {
  542.         (void)fprintf(stderr, "Short file %s\n", filename);
  543.         exit(1);
  544.         }
  545.         skip = (((data_size + 127) >> 7) << 7) - data_size;
  546.         for(j = 0; j < skip; j++) {
  547.         (void)fgetc(fd);
  548.         }
  549.     }
  550.     if(rsrc_size != 0) {
  551.         if(rsrc_size > max_rsrc_size) {
  552.         if(rsrc_fork == NULL) {
  553.             rsrc_fork = malloc((unsigned)rsrc_size);
  554.         } else {
  555.             rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  556.         }
  557.         max_rsrc_size = rsrc_size;
  558.         }
  559.         if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) {
  560.         (void)fprintf(stderr, "Short file %s\n", filename);
  561.         exit(1);
  562.         }
  563.     }
  564.     break;
  565. #ifdef APPLESHARE
  566.     case SHAREFILE:
  567. #ifdef AUFS
  568.     (void)strcpy(filename1, infodir);
  569.     (void)strcat(filename1, "/");
  570.     (void)strcat(filename1, filename);
  571.     if((fd = fopen(filename1, "r")) == NULL) {
  572.         (void)fprintf(stderr, "Cannot open file %s\n", filename1);
  573.     }
  574.     read_aufs_info(fd);
  575.     (void)fclose(fd);
  576.     (void)strcpy(filename1, rsrcdir);
  577.     (void)strcat(filename1, "/");
  578.     (void)strcat(filename1, filename);
  579.     if(stat(filename1, &stbuf) >= 0) {
  580.         rsrc_size = stbuf.st_size;
  581.         put4(file_info + I_RLENOFF, (unsigned long)rsrc_size);
  582.         if(rsrc_size > 0) {
  583.         if(rsrc_size > max_rsrc_size) {
  584.             if(rsrc_fork == NULL) {
  585.             rsrc_fork = malloc((unsigned)rsrc_size);
  586.             } else {
  587.             rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  588.             }
  589.             max_rsrc_size = rsrc_size;
  590.         }
  591.         if((fd = fopen(filename1, "r")) == NULL) {
  592.             (void)fprintf(stderr, "Cannot open file %s\n", filename1);
  593.             exit(1);
  594.         }
  595.         if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) {
  596.             (void)fprintf(stderr, "Short file %s\n", filename1);
  597.             exit(1);
  598.         }
  599.         (void)fclose(fd);
  600.         }
  601.     }
  602.     if(stat(filename, &stbuf) >= 0) {
  603.         data_size = stbuf.st_size;
  604.         put4(file_info + I_DLENOFF, (unsigned long)data_size);
  605.         if(data_size > 0) {
  606.         if(data_size > max_data_size) {
  607.             if(data_fork == NULL) {
  608.             data_fork = malloc((unsigned)data_size);
  609.             } else {
  610.             data_fork = realloc(data_fork, (unsigned)data_size);
  611.             }
  612.             max_data_size = data_size;
  613.         }
  614.         if((fd = fopen(filename, "r")) == NULL) {
  615.             (void)fprintf(stderr, "Cannot open file %s\n", filename);
  616.             exit(1);
  617.         }
  618.         if(fread(data_fork, 1, data_size, fd) != data_size) {
  619.             (void)fprintf(stderr, "Short file %s\n", filename1);
  620.             exit(1);
  621.         }
  622.         (void)fclose(fd);
  623.         }
  624.     }
  625. #endif /* AUFS */
  626. #ifdef APPLEDOUBLE
  627.     (void)strcpy(filename1, infodir);
  628.     (void)strcat(filename1, "/");
  629.     (void)strcat(filename1, filename);
  630.     if((fd = fopen(filename1, "r")) == NULL) {
  631.         (void)fprintf(stderr, "Cannot open file %s\n", filename1);
  632.     }
  633.     read_appledouble_info(fd);
  634.     rsrc_size = get4(file_info + I_RLENOFF);
  635.     if(rsrc_size > 0) {
  636.         if(rsrc_size > max_rsrc_size) {
  637.         if(rsrc_fork == NULL) {
  638.             rsrc_fork = malloc((unsigned)rsrc_size);
  639.         } else {
  640.             rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  641.         }
  642.         max_rsrc_size = rsrc_size;
  643.         }
  644.         if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) {
  645.         (void)fprintf(stderr, "Short file %s\n", filename1);
  646.         exit(1);
  647.         }
  648.     }
  649.     (void)fclose(fd);
  650.     if(stat(filename, &stbuf) >= 0) {
  651.         data_size = stbuf.st_size;
  652.         put4(file_info + I_DLENOFF, (unsigned long)data_size);
  653.         if(data_size > 0) {
  654.         if(data_size > max_data_size) {
  655.             if(data_fork == NULL) {
  656.             data_fork = malloc((unsigned)data_size);
  657.             } else {
  658.             data_fork = realloc(data_fork, (unsigned)data_size);
  659.             }
  660.             max_data_size = data_size;
  661.         }
  662.         if((fd = fopen(filename, "r")) == NULL) {
  663.             (void)fprintf(stderr, "Cannot open file %s\n", filename);
  664.             exit(1);
  665.         }
  666.         if(fread(data_fork, 1, data_size, fd) != data_size) {
  667.             (void)fprintf(stderr, "Short file %s\n", filename1);
  668.             exit(1);
  669.         }
  670.         (void)fclose(fd);
  671.         }
  672.     }
  673. #endif /* APPLEDOUBLE */
  674.     break;
  675. #endif /* APPLESHARE */
  676.     }
  677. }
  678.  
  679. static void enter_dir()
  680. {
  681.     DIR *directory;
  682.     struct dirstruct *curentry;
  683.     FILE *fd;
  684.     int n, j, namlen;
  685.     int listsize, cursize;
  686.     char *filetable;
  687.     filelist *new_files;
  688. #ifdef APPLESHARE
  689.     char filename1[255];
  690. #endif /* APPLESHARE */
  691.  
  692.     for(j = 0; j < INFOBYTES; j++) {
  693.     file_info[j] = 0;
  694.     }
  695.     (void)strcpy(file_info + I_NAMEOFF + 1, filename);
  696.     file_info[I_NAMEOFF] = strlen(filename);
  697.     directory = opendir(filename);
  698.     if(directory == NULL) {
  699.     (void)fprintf(stderr, "Cannot read directory %s\n", filename);
  700.     exit(1);
  701.     }
  702.     listsize = 1024;
  703.     filetable = malloc((unsigned)listsize);
  704.     cursize = 0;
  705.     n = 0;
  706.     while((curentry = readdir(directory)) != NULL) {
  707.     namlen = strlen(curentry->d_name);
  708.     if(namlen + 1 > listsize - cursize) {
  709.         listsize += 1024;
  710.         filetable = realloc(filetable, (unsigned)listsize);
  711.     }
  712.     (void)strcpy(filetable + cursize, curentry->d_name);
  713.     cursize += (namlen + 1);
  714.     n++;
  715.     }
  716.     filetable = realloc(filetable, (unsigned)cursize);
  717.     (void)closedir(directory);
  718.     new_files = (filelist *)malloc(sizeof(filelist));
  719.     new_files->nfiles = n;
  720.     new_files->files = (char **)malloc((unsigned)n * sizeof(char **));
  721.     new_files->kind = (int *)malloc((unsigned)n * sizeof(int));
  722.     new_files->previous = current_files;
  723.     new_files->current = 0;
  724.     cursize = 0;
  725.     for(j = 0; j < n; j++) {
  726.     new_files->files[j] = filetable + cursize;
  727.     cursize += (strlen(filetable + cursize) + 1);
  728.     }
  729.     (void)chdir(filename);
  730. #ifdef APPLESHARE
  731.     if((fd = fopen(f_name, "r")) != NULL) {
  732.     if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) {
  733.         (void)fprintf(stderr, "File error on %s\n", f_name);
  734.         exit(1);
  735.     }
  736.     file_info[I_NAMEOFF] |= 0x80;
  737.     (void)fclose(fd);
  738.     } else {
  739. #ifdef AUFS
  740.     (void)strcpy(filename1, "../");
  741.     (void)strcat(filename1, infodir);
  742.     (void)strcat(filename1, "/");
  743.     (void)strcat(filename1, filename);
  744.     if((fd = fopen(filename1, "r")) != NULL) {
  745.         read_aufs_info(fd);
  746.         (void)fclose(fd);
  747.     }
  748. #endif /* AUFS */
  749. #ifdef APPLEDOUBLE
  750.     (void)strcpy(filename1, infodir);
  751.     (void)strcat(filename1, "/.Parent");
  752.     if((fd = fopen(filename1, "r")) != NULL) {
  753.         read_appledouble_info(fd);
  754.         (void)fclose(fd);
  755.     }
  756. #endif /* APPLEDOUBLE */
  757.     file_info[I_NAMEOFF] |= 0x80;
  758.     }
  759. #else /* APPLESHARE */
  760.     if((fd = fopen(f_name, "r")) != NULL) {
  761.     if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) {
  762.         (void)fprintf(stderr, "File error on %s\n", f_name);
  763.         exit(1);
  764.     }
  765.     file_info[I_NAMEOFF] |= 0x80;
  766.     (void)fclose(fd);
  767.     }
  768. #endif /* APPLESHARE */
  769.     current_files = new_files;
  770.     check_files(0);
  771. }
  772.  
  773. static void exit_dir()
  774. {
  775.     filelist *old_files;
  776.     int i;
  777.  
  778.     for(i = 0; i < INFOBYTES; i++) {
  779.     file_info[i] = 0;
  780.     }
  781.     file_info[I_NAMEOFF] = 0x80;
  782.     old_files = current_files;
  783.     /* Do some garbage collection here! */
  784.     current_files = current_files->previous;
  785.     (void)free(old_files->files[0]);
  786.     (void)free((char *)old_files->files);
  787.     (void)free((char *)old_files->kind);
  788.     (void)free((char *)old_files);
  789.     (void)chdir("..");
  790. }
  791.  
  792. #ifdef APPLESHARE
  793. #ifdef AUFS
  794. static void read_aufs_info(fd)
  795. FILE *fd;
  796. {
  797.     FileInfo theinfo;
  798.     int i, n;
  799.     struct stat stbuf;
  800.  
  801.     for(i = 0; i < INFOBYTES; i++) {
  802.     file_info[i] = 0;
  803.     }
  804.     bzero((char *) &theinfo, sizeof(theinfo));
  805.     if(fread((char *)&theinfo, 1, sizeof(theinfo), fd) != sizeof(theinfo)) {
  806.     (void)fprintf(stderr, "Short AUFS info header for %s\n", filename);
  807.     exit(1);
  808.     }
  809.     if(theinfo.fi_magic1 & BYTEMASK != FI_MAGIC1 ||
  810.        theinfo.fi_version & BYTEMASK != FI_VERSION ||
  811.        theinfo.fi_magic & BYTEMASK != FI_MAGIC) {
  812.     (void)fprintf(stderr, "Magic number mismatch on %s\n", filename);
  813.     exit(1);
  814.     }
  815.     bcopy(theinfo.fi_fndr, file_info + I_TYPEOFF, 4);
  816.     bcopy(theinfo.fi_fndr + 4, file_info + I_AUTHOFF, 4);
  817.     bcopy(theinfo.fi_fndr + 8, file_info + I_FLAGOFF, 2);
  818.     if(theinfo.fi_bitmap & FI_BM_MACINTOSHFILENAME) {
  819.     n = strlen(theinfo.fi_macfilename);
  820.     (void)strncpy(file_info + I_NAMEOFF + 1, (char *)theinfo.fi_macfilename,
  821.         n);
  822.     } else if(theinfo.fi_bitmap & FI_BM_SHORTFILENAME) {
  823.     n = strlen(theinfo.fi_shortfilename);
  824.     (void)strncpy(file_info + I_NAMEOFF + 1,
  825.         (char *)theinfo.fi_shortfilename, n);
  826.     } else {
  827.     n = strlen(filename);
  828.     (void)strncpy(file_info + I_NAMEOFF + 1, filename, n);
  829.     }
  830.     file_info[I_NAMEOFF] = n;
  831. #ifdef AUFSPLUS
  832.     if(theinfo.fi_datemagic == FI_MAGIC &&
  833.        (theinfo.fi_datevalid & (FI_CDATE | FI_MDATE)) ==
  834.         (FI_CDATE | FI_MDATE)) {
  835.     put4(file_info + I_CTIMOFF, get4(theinfo.fi_ctime) + TIMEDIFF);
  836.     put4(file_info + I_MTIMOFF, get4(theinfo.fi_mtime) + TIMEDIFF);
  837.     } else {
  838.     if(fstat(fileno(fd), &stbuf) >= 0) {
  839.         put4(file_info + I_CTIMOFF,
  840.         (unsigned long)stbuf.st_ctime + TIMEDIFF);
  841.         put4(file_info + I_MTIMOFF,
  842.         (unsigned long)stbuf.st_mtime + TIMEDIFF);
  843.     }
  844.     }
  845. #else /* AUFSPLUS */
  846.     if(fstat(fileno(fd), &stbuf) >= 0) {
  847.     put4(file_info + I_CTIMOFF, (unsigned long)stbuf.st_ctime + TIMEDIFF);
  848.     put4(file_info + I_MTIMOFF, (unsigned long)stbuf.st_mtime + TIMEDIFF);
  849.     }
  850. #endif /* AUFSPLUS */
  851. }
  852. #endif /* AUFS */
  853.  
  854. #ifdef APPLEDOUBLE
  855. /* This version assumes that the AppleDouble info header is always the same
  856.    size and format.  I have not yet seen something that will lead me to
  857.    believe different.
  858. */
  859. static void read_appledouble_info(fd)
  860. FILE *fd;
  861. {
  862.     FileInfo theinfo;
  863.     int i, n;
  864.  
  865.     for(i = 0; i < INFOBYTES; i++) {
  866.     file_info[i] = 0;
  867.     }
  868.     bzero((char *) &theinfo, sizeof(theinfo));
  869.     if(fread((char *)&theinfo, 1, sizeof(theinfo), fd) != sizeof(theinfo)) {
  870.     (void)fprintf(stderr, "Short AppleDouble info header for %s\n",
  871.         filename);
  872.     exit(1);
  873.     }
  874.     if(get4(theinfo.fi_magic) != FI_MAGIC ||
  875.        get2(theinfo.fi_version) != FI_VERSION) {
  876.     (void)fprintf(stderr, "Magic number mismatch on %s\n", filename);
  877.     exit(1);
  878.     }
  879.     bcopy(theinfo.fi_type, file_info + I_TYPEOFF, 4);
  880.     bcopy(theinfo.fi_auth, file_info + I_AUTHOFF, 4);
  881.     bcopy(theinfo.fi_finfo, file_info + I_FLAGOFF, 2);
  882.     n = get4(theinfo.fi_namlen);
  883.     (void)strncpy(file_info + I_NAMEOFF + 1, theinfo.fi_name, n);
  884.     file_info[I_NAMEOFF] = n;
  885.     put4(file_info + I_CTIMOFF, get4(theinfo.fi_ctime) + TIMEDIFF);
  886.     put4(file_info + I_MTIMOFF, get4(theinfo.fi_mtime) + TIMEDIFF);
  887.     rsrc_size = get4(theinfo.fi_rsrc);
  888.     put4(file_info + I_RLENOFF, (unsigned long)rsrc_size);
  889. }
  890. #endif /* APPLEDOUBLE */
  891. #endif /* APPLESHARE */
  892.  
  893. static int get_stdin_file()
  894. {
  895.     int i, skip;
  896.  
  897.     i = fgetc(stdin);
  898.     if(i == EOF) {
  899.     return ISATEND;
  900.     }
  901.     (void)ungetc(i, stdin);
  902.     if(fread(file_info, 1, INFOBYTES, stdin) != INFOBYTES) {
  903.     (void)fprintf(stderr, "Short input\n");
  904.     exit(1);
  905.     }
  906.     if(file_info[0] != 0) {
  907.     (void)fprintf(stderr, "File is not MacBinary: %s\n", filename);
  908.     exit(1);
  909.     }
  910.     data_size = get4(file_info + I_DLENOFF);
  911.     rsrc_size = get4(file_info + I_RLENOFF);
  912.     if(file_info[I_LOCKOFF] & 1) {
  913.     file_info[I_FLAGOFF + 1] = PROTCT_MASK;
  914.     file_info[I_LOCKOFF] &= ~1;
  915.     }
  916.     if(data_size != 0) {
  917.     if(data_size > max_data_size) {
  918.         if(data_fork == NULL) {
  919.         data_fork = malloc((unsigned)data_size);
  920.         } else {
  921.         data_fork = realloc(data_fork, (unsigned)data_size);
  922.         }
  923.         max_data_size = data_size;
  924.     }
  925.     if(fread(data_fork, 1, data_size, stdin) != data_size) {
  926.         (void)fprintf(stderr, "Short input\n");
  927.         exit(1);
  928.     }
  929.     skip = (((data_size + 127) >> 7) << 7) - data_size;
  930.     for(i = 0; i < skip; i++) {
  931.         (void)fgetc(stdin);
  932.     }
  933.     }
  934.     if(rsrc_size != 0) {
  935.     if(rsrc_size > max_rsrc_size) {
  936.         if(rsrc_fork == NULL) {
  937.         rsrc_fork = malloc((unsigned)rsrc_size);
  938.         } else {
  939.         rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size);
  940.         }
  941.         max_rsrc_size = rsrc_size;
  942.     }
  943.     if(fread(rsrc_fork, 1, rsrc_size, stdin) != rsrc_size) {
  944.         (void)fprintf(stderr, "Short input\n");
  945.         exit(1);
  946.     }
  947.     skip = (((rsrc_size + 127) >> 7) << 7) - rsrc_size;
  948.     for(i = 0; i < skip; i++) {
  949.         (void)fgetc(stdin);
  950.     }
  951.     }
  952.     if(file_info[I_NAMEOFF] & 0x80) {
  953.     if((file_info[I_NAMEOFF] & 0xff) == 0x80) {
  954.         return ENDDIR;
  955.     }
  956.     return ISDIR;
  957.     }
  958.     return ISFILE;
  959. }
  960.  
  961. int rdfileopt(c)
  962. char c;
  963. {
  964. extern char *optarg;
  965. char name[32];
  966.  
  967.     switch(c) {
  968.     case 'd':
  969.     data_only = DATA_FORMAT;
  970.     break;
  971.     case 'u':
  972.     case 'U':
  973.     data_only = UNIX_FORMAT;
  974.     break;
  975.     case 'r':
  976.     data_only = RSRC_FORMAT;
  977.     break;
  978.     case 'c':
  979.     backtrans(name, optarg);
  980.     (void)strncpy(f_auth, name, 4);
  981.     break;
  982.     case 't':
  983.     backtrans(name, optarg);
  984.     (void)strncpy(f_type, name, 4);
  985.     break;
  986.     default:
  987.     return 0;
  988.     }
  989.     return 1;
  990. }
  991.  
  992. void give_rdfileopt()
  993. {
  994.     (void)fprintf(stderr, "File input options:\n");
  995.     (void)fprintf(stderr, "-r:\tread as resource files\n");
  996.     (void)fprintf(stderr, "-d:\tread as data files\n");
  997.     (void)fprintf(stderr,
  998.     "-u:\tread as data files with Unix -> Mac text file translation\n");
  999.     (void)fprintf(stderr, "-U:\ta synonym for -u\n");
  1000.     (void)fprintf(stderr,
  1001.     "-c cr:\tcreator if one of the above options is used\n");
  1002.     (void)fprintf(stderr,
  1003.     "-t ty:\tfiletype if one of the above options is used\n");
  1004. }
  1005.  
  1006. void set_norecurse()
  1007. {
  1008.     no_recurse = 1;
  1009. }
  1010.  
  1011. char *get_rdfileopt()
  1012. {
  1013.     static char options[] = "rduUc:t:";
  1014.  
  1015.     return options;
  1016. }
  1017.  
  1018. char *get_minb()
  1019. {
  1020. #ifdef APPLESHARE
  1021. #ifdef AUFS
  1022.     return ", AUFS supported";
  1023. #endif /* AUFS */
  1024. #ifdef APPLEDOUBLE
  1025.     return ", AppleDouble supported";
  1026. #endif /* APPLEDOUBLE */
  1027. #else /* APPLESHARE */
  1028.     return ", no Apple-Unix sharing supported";
  1029. #endif /* APPLESHARE */
  1030. }
  1031.  
  1032.