home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / util / unix / macutil2.sha / macutil / fileio / rdfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-05  |  25.3 KB  |  977 lines

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