home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd2.lzh / TAR / tar.c < prev    next >
C/C++ Source or Header  |  1990-05-12  |  23KB  |  1,072 lines

  1. char scid[]="$Header: tar.c,v 1.8  04/13/90 SrT/stp $";
  2.  
  3. /*
  4.  * Modified for use under OS-9/68k  (08/03/89)
  5.  * Stephan Paschedag  stp@ethz.uucp   ..!mcvax!cernvax!chx400!ethz!stp
  6.  *                    paschedag@strati.ethz.ch
  7.  *
  8.  * Compilation for OS-9/68k:  cc -qi tar.c
  9.  *
  10.  * 04/13/90  V1.8  problems in extraction of subdirectories fixed
  11.  *                 change invalid filenames
  12.  *                 LF <-> CR conversion added (u modifier) (stp)
  13.  *
  14.  * 01/28/90  V1.7  multi-file buffer implemented (stp)
  15.  *
  16.  * 01/16/90  V1.6  Copy buffer implemeted, results in much faster
  17.  *                 (re-)storing times (stp)
  18.  *
  19.  * 08/06/89  V1.5  Allow extraction of entire directories,
  20.  *                 allow extraction of single files in subdirectories,
  21.  *                 creates automatically missing directories.
  22.  *                 continues now correctly after some errors
  23.  *                 handles directories from unix archives correctly (stp)
  24.  *
  25.  * Modified for use under OS-9/6809
  26.  * Simmule Turner   simmy@nu.cs.fsu.edu   70651,67
  27.  *
  28.  * Compilation for OS-9/6809:  cc -m=3k tar.c
  29.  *     Use extra memory for recursive directory descents.
  30.  *
  31.  * 07/17/88  V1.4  Allow extraction of specified file(s)....
  32.  *                 from archive named on the command line
  33.  *                 with wildcard matching *,?. (SrT)
  34.  *
  35.  * 07/14/88  V1.3  Added verbose TOC ala unix.  Cleaned up
  36.  *                 printing routines, use decimal instead of
  37.  *                 octal. Removed conditional compilation. (SrT)
  38.  *
  39.  * 07/13/88  V1.2  Tries to set the correct file permissions.
  40.  *                 Send diagnostics to stderr.  Use lseek's
  41.  *                 for TOC generation when a rbf device. (SrT)
  42.  *
  43.  * 07/12/88  V1.1  Added option of reading/writing
  44.  *                 archive to stdin/stdout (SrT)
  45.  *
  46.  * 07/12/88  V1.0  Initial port (SrT)
  47.  *                 added dummy fv options
  48.  * SrT */
  49.  
  50. /* tar - tape archiver          Author: Michiel Huisjes */
  51.  
  52. /* Usage: tar [cxt][bdfmuv] tapefile [files]
  53.  *
  54.  * Bugs:
  55.  *  This tape archiver should only be used as a program to read or make
  56.  *  simple tape archives. Its basic goal is to read (or build) UNIX V7 tape
  57.  *  archives and extract the named files. It is not wise to use it on
  58.  *  raw magnetic tapes. It doesn't know anything about linked files,
  59.  *  except when the involved fields are filled in.
  60.  *
  61.  * Comment : It works fine on raw magnetic tapes ! (tar tv /mt0 .)
  62.  */
  63.  
  64. #include <stdio.h>
  65. #include <direct.h>
  66. #include <modes.h>
  67. #include <sgstat.h>
  68. #include <time.h>
  69. #ifndef OSK
  70. #  include <utime.h>
  71. #else
  72. #  include <types.h>
  73. #  include <errno.h>
  74. #  include <strings.h>
  75. #endif
  76.  
  77. #define STDIN   0
  78. #define STDOUT  1
  79.  
  80. typedef char BOOL;
  81. #define TRUE    1
  82. #define FALSE   0
  83.  
  84. #define HEADER_SIZE     512
  85. #define NAME_SIZE       100
  86. #define BLOCK_BOUNDARY   20
  87.  
  88. typedef union {
  89.   char hdr_block[HEADER_SIZE];
  90.   struct m {
  91.     char m_name[NAME_SIZE];
  92.     char m_mode[8];
  93.     char m_uid[8];
  94.     char m_gid[8];
  95.     char m_size[12];
  96.     char m_time[12];
  97.     char m_checksum[8];
  98.     char m_linked;
  99.     char m_link[NAME_SIZE];
  100.   } member;
  101. } HEADER;
  102.  
  103. /* file match structure (04/13/90 stp) */
  104. struct files {
  105.   char *name;
  106.   struct files *next;
  107. };
  108.  
  109. HEADER header;
  110.  
  111. #define INT_TYPE    (sizeof(header.member.m_uid))
  112. #define LONG_TYPE   (sizeof(header.member.m_size))
  113.  
  114. #define NIL_HEADER  ((HEADER *) 0)
  115. #define NIL_PTR     ((char *) 0)
  116. #define BLOCK_SIZE  512
  117.  
  118. #define flush()     print(NIL_PTR)
  119.  
  120. BOOL show_fl, creat_fl, ext_fl, verbose_fl, modtime_fl, convert_fl, disk_fl;
  121.  
  122. char modestr[11], stbuf[132];
  123. struct sgbuf opts;
  124. struct fildes ofdbuf;
  125. #ifdef OSK
  126. char *dummy = NULL;
  127. #endif
  128.  
  129. int tar_fd;
  130.  
  131. /* set blocksize  (01/16/90 stp) */
  132. BOOL blks_fl;
  133. int blocking = 1;
  134. char *io_buffer;
  135. char *w_buffer;
  136. long bsize;
  137.  
  138. int total_blocks;
  139. long convert();
  140. char **match();
  141.  
  142. block_size() {
  143.     return ((int) ((convert(header.member.m_size, LONG_TYPE)
  144.             + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE));
  145. }
  146.  
  147. error(s1, s2)
  148. char *s1, *s2;
  149. {
  150. #ifdef OSK
  151.   fprintf(stderr,"%s %s\n", s1, s2 ? s2 : "");
  152.   exit(1);
  153. #else
  154.   string_print(NIL_PTR, "%s %s\r\l", s1, s2 ? s2 : "");
  155.   flush();
  156.   exit(1);
  157. #endif
  158. }
  159.  
  160. usage() {
  161.   fprintf(stderr,"Syntax : tar [ctxb][mfvu] [blocks] tarfile [file(s)...]\n");
  162.   fprintf(stderr,"Function: Builds and extracts from Unix tape archive files\n");
  163.   fprintf(stderr,"Options:                      Modifiers:\n");
  164.   fprintf(stderr,"   c : create archive            b : set copy buffer size\n");
  165.   fprintf(stderr,"   t : list contents             d : backup floppy disks\n");
  166.   fprintf(stderr,"   x : extract from archive      m : do not restore date\n");
  167.   fprintf(stderr,"                                 u : convert LF <-> CR\n");
  168.   fprintf(stderr,"                                 v : verbose mode\n");
  169.   exit(0);
  170. }
  171.  
  172. main(argc, argv)
  173. int argc;
  174. register char *argv[];
  175. {
  176.     register char *ptr;
  177. #ifdef OSK
  178.     char **p = &dummy;
  179. #else
  180.     char **p = "\0";
  181. #endif
  182.     int i;
  183.  
  184.   pflinit();
  185.  
  186.   if (argc < 3)
  187.     usage();
  188.  
  189.   for (ptr = argv[1]; *ptr; ptr++) {
  190.     switch (*ptr) {
  191.         case 'c' :
  192.             creat_fl = TRUE;
  193.             break;
  194.         case 't' :
  195.             show_fl = TRUE;
  196.             break;
  197.         case 'x' :
  198.             ext_fl  = TRUE;
  199.             break;
  200. /*
  201.  * Modifiers
  202.  * SrT */
  203. /* set blocksize  (01/16/90 stp) */
  204.         case 'b' :
  205.             blks_fl = TRUE;
  206.             break;
  207. /* muliple disk backup (04/14/90 stp) */
  208.         case 'd' :
  209.             disk_fl = TRUE;
  210.             break;
  211.         case 'f':
  212.             break;
  213.         case 'm':
  214.             modtime_fl = TRUE;
  215.             break;
  216.         case 'v':
  217.             verbose_fl = TRUE;
  218.             break;
  219. /* convert flag (04/10/90 stp) */
  220.         case 'u' :
  221.             convert_fl = TRUE;
  222.             break;
  223.         default :
  224.             usage();
  225.     }
  226.   }
  227.  
  228.   if (blks_fl) {
  229.     if (sscanf(argv[2],"%d",&blocking) == -1)
  230.       error("bad parameter for blocking",argv[3]);
  231.     blocking = (blocking+1)>>1;
  232.   }
  233.  
  234.   if ((io_buffer = (char*) malloc(BLOCK_SIZE*blocking)) == 0)
  235.     error("allocation of io_buffer failed","");
  236.   if ((w_buffer = (char *) malloc(BLOCK_SIZE*blocking)) == 0)
  237.     error("allocation of w_buffer failed","");
  238.   bsize = (long) BLOCK_SIZE*blocking;
  239.  
  240.   if (ext_fl) {
  241.     if (argc > (blks_fl ? 4 : 3))
  242.       p = &argv[blks_fl ? 4 : 3];
  243.   }
  244.  
  245.   if (creat_fl + ext_fl + show_fl != 1)
  246.     usage();
  247.  
  248.   if (argv[blks_fl ? 3 : 2][0] == '-')
  249.      tar_fd = creat_fl ? STDOUT : STDIN;
  250.   else
  251.      tar_fd = creat_fl ? creat(argv[blks_fl ? 3 : 2],3) : open(argv[blks_fl ? 3 : 2],1);
  252.  
  253.   if (tar_fd < 0) {
  254. #ifdef OSK
  255.     exit(_errmsg(errno,"cannot open archive. "));
  256. #else
  257.     error("Cannot open ", argv[blks_fl ? 3 : 2]);
  258. #endif
  259.   }
  260.  
  261.   if (creat_fl) {
  262.     do {
  263.       for (i = (blks_fl ? 4 : 3); i < argc; i++)
  264.         add_file(argv[i]);
  265.       if (disk_fl) {
  266.         do {
  267.           printf("save another disk ?"); fflush(stdout);
  268.           i = toupper(getchar());
  269.         } while ((i != 'Y') && (i != 'N'));
  270.         disk_fl = (i == 'Y');
  271.       }
  272.     } while(disk_fl);
  273.     adjust_boundary();
  274.   }
  275.   else
  276.     tarfile (p);
  277.  
  278.   flush();
  279.   exit(0);
  280. }
  281.  
  282. BOOL get_header()
  283. {
  284.   register int check,c;
  285.  
  286.   mread(tar_fd, &header, sizeof(header));
  287.   if (header.member.m_name[0] == '\0')
  288.     return FALSE;
  289.  
  290.   check = (int) convert(header.member.m_checksum, INT_TYPE);
  291.  
  292.   if (check != (c = checksum()))
  293.     error("tar: header checksum error.", NIL_PTR);
  294.  
  295.   return TRUE;
  296. }
  297.  
  298. tarfile(p)
  299.     char **p;
  300. {
  301.   register char *ptr;
  302.   register char *mem_name;
  303.   char *atime();
  304.   int i;
  305.   register char **q;
  306.   register char *pp;
  307.   struct files f0,*fptr=&f0;
  308.  
  309. /* create 'files' structure from 'p' */
  310.   q = p;
  311.   while (*q) {
  312.     fptr->name = (char *) malloc(strlen(*q));
  313.     strcpy(fptr->name,*q);
  314.     fptr->next = (struct files*) malloc(sizeof(struct files));
  315.     fptr = fptr->next;
  316.     q++;
  317.   }
  318.   fptr->name = 0;
  319.  
  320.   _gs_opt(tar_fd,&opts);
  321.  
  322.   while (get_header()) {
  323.     mem_name = header.member.m_name;
  324.     if (ext_fl) {
  325.         if (*p) {
  326. /* extract entire directories (08/05/89 stp) */
  327.             if (mem_name[strlen(mem_name)-1] == '/') {
  328.               mem_name[strlen(mem_name)-1] = '\0';
  329.               if (q=match(&f0,mem_name)) {
  330.                 fptr->name = (char *) malloc(strlen(mem_name)+3);
  331.                 strcpy(fptr->name,mem_name);
  332.                 strncat(fptr->name,"/*",3);
  333.                 fptr->next = (struct files*) malloc(sizeof(struct files));
  334.                 fptr = fptr->next;
  335.                 fptr->name = 0;
  336.                 check_name(mem_name);
  337.                 mkdir(mem_name);
  338.               }
  339.               else {
  340.                 q = q;
  341.               }
  342.             }
  343.             else {
  344.               if (match(&f0,mem_name)) {
  345.                 extract(mem_name);
  346.               }
  347.               else
  348.                 skip_entry();
  349.             }
  350.         }
  351.         else {
  352.             if (is_dir(mem_name)) {
  353.                 for (ptr = mem_name; *ptr != '/'; ptr++);
  354.                 *ptr = '\0';
  355.                 check_name(mem_name);
  356.                 mkdir(mem_name);
  357.             }
  358.             else {
  359.               extract(mem_name);
  360.             }
  361.         }
  362.     }
  363.     else  {
  364.         if (!verbose_fl)
  365. #ifdef OSK
  366.             printf("%s",mem_name);
  367. #else
  368.             string_print(NIL_PTR, "%s", mem_name);
  369. #endif
  370.         else {
  371.             u29mode((int) convert(header.member.m_mode,INT_TYPE));
  372. #ifdef OSK
  373.             printf("%s ",modestr);
  374. #else
  375.             string_print(NIL_PTR, "%s ",modestr);
  376. #endif
  377.             sprintf(stbuf,"%3d/%3d %8ld %s %s",
  378.                 (int) convert(header.member.m_uid, INT_TYPE),
  379.                 (int) convert(header.member.m_gid, INT_TYPE),
  380.                       convert(header.member.m_size,LONG_TYPE),
  381.                       atime(convert(header.member.m_time,LONG_TYPE)),
  382.                       header.member.m_name);
  383. #ifdef OSK
  384.             printf("%s",stbuf);
  385.         }
  386.         printf("\n");
  387. #else
  388.             print(stbuf);
  389.         }
  390.         print("\r\l");
  391. #endif
  392.         skip_entry();
  393.     }
  394.     flush();
  395.   }
  396. }
  397.  
  398. skip_entry()
  399. {
  400.   register int blocks = block_size();
  401.  
  402.     if (opts.sg_class == 1) {
  403.         long pos;
  404.  
  405.         pos = ((long) blocks) * BLOCK_SIZE;
  406.         lseek(tar_fd,pos,1);
  407.     }
  408.     else {
  409.         while (blocks--)
  410.             read(tar_fd, io_buffer, BLOCK_SIZE);
  411.     }
  412. }
  413.  
  414. /* convert to valid filename */
  415. check_name(c)
  416. register char *c;
  417. {
  418.   while (*c) {
  419.     if (((*c >= '0') && (*c <= '9')) ||
  420.         ((*c >= 'A') && (*c <= 'Z')) ||
  421.         ((*c >= 'a') && (*c <= 'z')) ||
  422.         (*c == '_') || (*c == '$') || (*c == '.') || (*c == '/')) {
  423.     }
  424.     else {
  425.       *c = '_';
  426.     }
  427.     c++;
  428.   }
  429. }
  430.  
  431. extract(file)
  432. register char *file;
  433. {
  434.   register int fd;
  435.  
  436.   if (header.member.m_linked == '1') {
  437. #ifdef OSK
  438.     fprintf(stderr,"Cannot link %s (symbolic links not supportet)\n",header.member.m_link);
  439. #else
  440.     string_print(NIL_PTR,"Cannot link %s\r\l",header.member.m_link);
  441. #endif
  442.     skip_entry();
  443.     return(0);
  444.   }
  445.  
  446.   check_name(file);
  447.   if ((fd = creat(file, 3)) < 0) {
  448. /* create missing directories (08/06/89) stp */
  449. register char *s,*pp;
  450.     pp = file;
  451. #ifdef OSK
  452.     while (s = index(pp,'/')) {
  453. #else
  454.     while (s = strchr(pp,'/')) {
  455. #endif
  456.       pp = (char *) malloc(s-file+1);
  457.       strncpy(pp,file,s-file);
  458.       pp[s-file] = '\0';
  459.       mkdir(pp);
  460.       free(pp);
  461.       pp = s+1;
  462.     }
  463.     if ((fd = creat(file, 3)) < 0) {
  464. #ifdef OSK
  465.       fprintf(stderr, "Cannot create %s : ", file); fflush(stderr);
  466.       prerr(0,errno);
  467. #else
  468.       string_print(NIL_PTR, "Cannot create %s\r\l", file);
  469. #endif
  470.       skip_entry();
  471.       return(0);
  472.     }
  473.   }
  474.  
  475.   copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
  476.  
  477.   _ss_attr(fd, u29mode((int) convert(header.member.m_mode, INT_TYPE)));
  478.  
  479.   if (!modtime_fl)
  480. #ifdef OSK
  481.         if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != -1) {
  482. #else
  483.         if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != ERROR) {
  484. #endif
  485.  
  486.             struct tm     *utm;
  487.             struct sgtbuf otm;
  488.             long clock;
  489.  
  490.             clock = convert(header.member.m_time,LONG_TYPE);
  491.             utm = localtime(&clock);
  492.             u2otime(&otm,utm);
  493.             _strass(&ofdbuf.fd_date[0], &otm, 5);
  494.             _ss_pfd(fd,&ofdbuf);
  495.         }
  496.  
  497.     close(fd);
  498.     flush();
  499. }
  500.  
  501. /* convert one char from buffer to another char (04/10/90 stp) */
  502. convert_buf(p,s,f,t)
  503. register char *p; /* *buffer */
  504. register int s;   /* size of buffer */
  505. register f,t;     /* from, to */
  506. {
  507.   while (s--) {
  508.     if (*p == f)
  509.       *p = t;
  510.     p++;
  511.   }
  512. }
  513.  
  514. copy(file, from, to, bytes)
  515. char *file;
  516. int from, to;
  517. register long bytes;
  518. {
  519.   register int rest,cnt;
  520.   int blocks,blks_fl = (int) ((bytes + BLOCK_SIZE - 1) / BLOCK_SIZE);
  521.  
  522.   if (verbose_fl) {
  523.      if (to == tar_fd) {
  524. #ifdef OSK
  525.         printf("a %s, ",file); fflush(stdout);
  526. #else
  527.         sprintf(stbuf,"a %s, %d tape blocks\r\l",file,blks_fl);
  528. #endif
  529.      }
  530.      else {
  531. #ifdef OSK
  532.         printf("x %s, %ld bytes, ",file,bytes); fflush(stdout);
  533.      }
  534. #else
  535.         sprintf(stbuf,"x %s, %ld bytes, %d tape blocks\r\l",file,bytes,blks_fl);
  536.      }
  537.      print(stbuf);
  538.      flush();
  539. #endif
  540.   }
  541.  
  542.   blocks = (int) ((bytes + bsize - 1) / bsize);
  543.  
  544.   while (blocks--) {
  545.     cnt = rest = (bytes > bsize) ? bsize : (to == tar_fd ? (int) bytes :
  546.                     ((bytes + BLOCK_SIZE - 1) / BLOCK_SIZE)*BLOCK_SIZE);
  547.     read(from, io_buffer, rest);
  548.     rest = (bytes > bsize) ? bsize : (to == tar_fd ? ((bytes + BLOCK_SIZE - 1) / BLOCK_SIZE)*BLOCK_SIZE :
  549.                                       bytes);
  550.     if (convert_fl)
  551.       if (to == tar_fd) {
  552.         convert_buf(io_buffer,rest,0x0d,0x0a);
  553.       }
  554.       else {
  555.         convert_buf(io_buffer,rest,0x0a,0x0d);
  556.       }
  557.     mwrite(to, io_buffer, rest,0);
  558.     bytes -= (bytes > bsize ? bsize : bytes);
  559.   }
  560. #ifdef OSK
  561.   if (verbose_fl)
  562.     printf("%d tape blocks\n",blks_fl);
  563. #endif
  564. }
  565.  
  566. long convert(str, type)
  567. char str[];
  568. int type;
  569. {
  570.   register long ac = 0L;
  571.   register int i;
  572.  
  573.   for (i = 0; i < type; i++) {
  574.     if (str[i] >= '0' && str[i] <= '7') {
  575.         ac <<= 3;
  576.         ac += (long) (str[i] - '0');
  577.     }
  578.   }
  579.  
  580.   return ac;
  581. }
  582.  
  583. mkdir(dir_name)
  584. char *dir_name;
  585. {
  586.   if (mknod(dir_name,3) < 0) {
  587.      return(0);
  588.   }
  589.   else {
  590.     int fd;
  591.     if ((fd = open(dir_name,0x83)) > 0) {
  592.         _ss_attr(fd, S_IFDIR | u29mode((int) convert(header.member.m_mode, INT_TYPE)));
  593.         close(fd);
  594.     }
  595.   }
  596. }
  597.  
  598. checksum()
  599. {
  600.   register char *ptr = header.member.m_checksum;
  601.   register int ac = 0;
  602.  
  603.   while (ptr < &header.member.m_checksum[INT_TYPE])
  604.     *ptr++ = ' ';
  605.  
  606.   ptr = header.hdr_block;
  607.   while (ptr < &header.hdr_block[BLOCK_SIZE])
  608.     ac += *ptr++;
  609.  
  610.   return ac;
  611. }
  612.  
  613. is_dir(file)
  614. register char *file;
  615. {
  616.   while (*file++ != '\0') ;
  617.   return (*(file - 2) == '/');
  618. }
  619.  
  620. char path[NAME_SIZE];
  621.  
  622. char pathname[NAME_SIZE];
  623. char *path_name(file)
  624. register char *file;
  625. {
  626.  
  627.   string_print(pathname, "%s%s", path, file);
  628.   return pathname;
  629. }
  630.  
  631. add_path(name)
  632. register char *name;
  633. {
  634.   register char *path_ptr = path;
  635.  
  636.   while (*path_ptr)
  637.     path_ptr++;
  638.  
  639.   if (name == NIL_PTR) {
  640.     while (*path_ptr-- != '/')
  641.         ;
  642.     while (*path_ptr != '/' && path_ptr != path)
  643.         path_ptr--;
  644.     if (*path_ptr == '/')
  645.         path_ptr++;
  646.     *path_ptr = '\0';
  647.   }
  648.   else {
  649.     while (*name) {
  650.         if (path_ptr == &path[NAME_SIZE])
  651.             error("tar: Pathname too long", NIL_PTR);
  652.         *path_ptr++ = *name++;
  653.     }
  654.     *path_ptr++ = '/';
  655.     *path_ptr = '\0';
  656.   }
  657. }
  658.  
  659. add_file(file)
  660. register char *file;
  661. {
  662.   struct fildes st;
  663.   struct dirent dir;
  664.   register int fd;
  665. #ifdef OSK
  666.   unsigned long siz;
  667.   u_char *sip = (u_char*) st.fd_fsize;
  668. #endif
  669.  
  670.   if ((fd = open(file,0x81)) < 0)
  671.      if ((fd = open(file, 1)) < 0) {
  672. #ifdef OSK
  673.         fprintf(stderr, "Cannot open '%s' ", file); fflush(stderr);
  674.         prerr(0,errno);
  675. #else
  676.         string_print(NIL_PTR, "Cannot open %s\r\l", file);
  677. #endif
  678.         return(0);
  679.      }
  680.   if (_gs_gfd(fd,&st,sizeof(st)) < 0) {
  681. #ifdef OSK
  682.      fprintf(stderr, "Cannot get file descriptor for %s",file); fflush(stderr);
  683.      prerr(0,errno);
  684. #else
  685.      string_print(NIL_PTR, "Cannot get file descriptor for %s\r\l",file);
  686. #endif
  687.      close(fd);
  688.      return(0);
  689.   }
  690.   siz = (((((sip[0] << 8) + sip[1]) << 8) + sip[2]) << 8) + sip[3];
  691.  
  692.   make_header(path_name(file), &st);
  693.   mwrite(tar_fd, &header, sizeof(header),0);
  694.   if (!(st.fd_att & S_IFDIR))
  695. #ifdef OSK
  696.      copy(path_name(file), fd, tar_fd, siz);
  697. #else
  698.      copy(path_name(file), fd, tar_fd, st.fd_fsize);
  699. #endif
  700.   else if (st.fd_att & S_IFDIR) {
  701.     if (chdir(file) < 0)
  702.         string_print(NIL_PTR, "Cannot chdir to %s\n", file);
  703.     else {
  704.         add_path(file);
  705.         mread(fd, &dir, sizeof(dir));       /* "." */
  706.         mread(fd, &dir, sizeof(dir));       /* ".." */
  707.         while (read(fd, &dir, sizeof(dir)) == sizeof(dir)) {
  708. #ifdef OSK
  709.             if (dir.dir_addr) {
  710. #else
  711.             if (dir.dir_addr[0] || dir.dir_addr[1] || dir.dir_addr[2]) {
  712. #endif
  713.                 strhcpy(dir.dir_name,dir.dir_name);
  714.                 if (*dir.dir_name)
  715.                   add_file(dir.dir_name);
  716.             }
  717.         }
  718.         chdir("..");
  719.         add_path(NIL_PTR);
  720.     }
  721.   }
  722.   else
  723. #ifdef OSK
  724.     _errmsg("unknown file type. Not added. ",0);
  725. #else
  726.     print("tar: unknown file type. Not added.\r\l");
  727. #endif
  728.  
  729.   close(fd);
  730. }
  731.  
  732. make_header(file, st)
  733. char *file;
  734. register struct fildes *st;
  735. {
  736.   register char *ptr = header.member.m_name;
  737.   char tbuf[6];
  738. #ifdef OSK
  739.   u_char *sip = (u_char*) st->fd_fsize;
  740.   unsigned long siz = (((((sip[0] << 8) + sip[1]) << 8) +
  741.                          sip[2]) << 8) + sip[3];
  742.   u_char *owp = (u_char*) st->fd_own;
  743.   unsigned short own = owp[1];
  744.   unsigned short group = owp[0];
  745. #endif
  746.  
  747.   clear_header();
  748.  
  749.   while (*ptr++ = *file++)
  750.     ;
  751.  
  752.   if (st->fd_att &  S_IFDIR) {
  753.     *(ptr - 1) = '/';
  754. #ifdef OSK
  755.     siz = 0;
  756. #else
  757.     st->fd_fsize = 0L;
  758. #endif
  759.   }
  760.  
  761.   _strass(tbuf,st->fd_date,5);
  762.   tbuf[5] = 0;
  763.   string_print(header.member.m_mode, "%I ", o2umode(st->fd_att));
  764. #ifdef OSK
  765.   string_print(header.member.m_uid,  "%I ", own);
  766.   string_print(header.member.m_gid,  "%I ", group);
  767.   string_print(header.member.m_size, "%L ", siz);
  768. #else
  769.   string_print(header.member.m_uid,  "%I ", st->fd_own);
  770.   string_print(header.member.m_gid,  "%I ", 101);
  771.   string_print(header.member.m_size, "%L ", st->fd_fsize);
  772. #endif
  773.   string_print(header.member.m_time, "%L ", o2utime(tbuf));
  774.   header.member.m_linked = ' ';
  775.   string_print(header.member.m_checksum, "%I", checksum());
  776. }
  777.  
  778. clear_header()
  779. {
  780.   register char *ptr = header.hdr_block;
  781.  
  782.   while (ptr < &header.hdr_block[BLOCK_SIZE])
  783.     *ptr++ = '\0';
  784. }
  785.  
  786. adjust_boundary()
  787. {
  788.   clear_header();
  789.   mwrite(tar_fd, &header, sizeof(header),1);
  790.  
  791.   while (total_blocks++ < BLOCK_BOUNDARY)
  792.     mwrite(tar_fd, &header, sizeof(header),1);
  793.   close(tar_fd);
  794. }
  795.  
  796. mread(fd, address, bytes)
  797. int fd, bytes;
  798. char *address;
  799. {
  800. register int r;
  801.  
  802.   if ((r = read(fd, address, bytes)) != bytes) {
  803. #ifdef OSK
  804.     if (r == 0)
  805.       errno = E_EOF;
  806.     exit(_errmsg(errno,"read error. "));
  807. #else
  808.     error("tar: read error.", NIL_PTR);
  809. #endif
  810.   }
  811. }
  812.  
  813. mwrite(fd, address, bytes, flag)
  814. int fd, bytes;
  815. char *address;
  816. short flag;
  817. {
  818. static char *bptr;
  819. static int fill = 0;
  820.  
  821.   if (fd == tar_fd) {
  822.     if (fill == 0)
  823.       bptr = w_buffer;
  824.     while (fill + bytes > bsize) {
  825.       _strass(bptr,address,bsize-fill);
  826.       write(fd,w_buffer,bsize);
  827.       address += (bsize-fill);
  828.       bytes -= (bsize-fill);
  829.       fill = 0;
  830.       bptr = w_buffer;
  831.     }
  832.     _strass(bptr,address,bytes);
  833.     bptr += bytes;
  834.     fill += bytes;
  835.     if (flag) {
  836.       write(fd,w_buffer,fill);
  837.       fill = 0;
  838.     }
  839.   }
  840.   else {
  841.     if (write(fd, address, bytes) != bytes) {
  842. #ifdef OSK
  843.       exit(_errmsg(errno,"write error. "));
  844. #else
  845.       error("tar: write error.", NIL_PTR);
  846. #endif
  847.     }
  848.   }
  849.   total_blocks++;
  850. }
  851.  
  852. char output[BLOCK_SIZE];
  853. print(str)
  854. register char *str;
  855. {
  856.   static int index = 0;
  857.  
  858.   if (str == NIL_PTR) {
  859.     write(2, output, index);
  860.     index = 0;
  861.     return(0);
  862.   }
  863.  
  864.   while (*str) {
  865.     output[index++] = *str++;
  866.     if (index == BLOCK_SIZE) {
  867.         write(2, output, BLOCK_SIZE);
  868.         index = 0;
  869.     }
  870.   }
  871. }
  872.  
  873. char *num_out(number)
  874. register long number;
  875. {
  876.   static char num_buf[13];
  877.   char temp[13];
  878.   register int i;
  879.  
  880.   for (i = 0; i < 11; i++) {
  881.     temp[i] = (number & 07) + '0';
  882.     number >>= 3;
  883.   }
  884.  
  885.   for (i = 0; i < 11; i++)
  886.     num_buf[i] = temp[10 - i];
  887.  
  888.   return num_buf;
  889. }
  890.  
  891. /* VARARGS */
  892. string_print(buffer, fmt, args)
  893. char *buffer;
  894. register char *fmt;
  895. int args;
  896. {
  897.   register char *buf_ptr;
  898.   char *scan_ptr;
  899.   char buf[NAME_SIZE];
  900.   int *argptr = &args;
  901.   BOOL pr_fl, i;
  902.  
  903.   if ((pr_fl = (buffer == NIL_PTR)))
  904.     buffer = buf;
  905.  
  906.   buf_ptr = buffer;
  907.   while (*fmt) {
  908.     if (*fmt == '%') {
  909.         fmt++;
  910.         switch (*fmt++) {
  911.             case 's':
  912.                 scan_ptr = (char *) *argptr;
  913.                 break;
  914.             case 'I':
  915.                 scan_ptr = num_out((long) *argptr) + 5;
  916. /*                for (i = 0; i < 5; i++)
  917.                     scan_ptr++; */
  918.                 break;
  919.             case 'L':
  920.                 scan_ptr = num_out(*((long *) argptr));
  921.                 argptr++;
  922.                 break;
  923.             default:
  924.                 scan_ptr = "";
  925.         }
  926.         while (*buf_ptr++ = *scan_ptr++)
  927.             ;
  928.         buf_ptr--;
  929.         argptr++;
  930.     }
  931.     else
  932.         *buf_ptr++ = *fmt++;
  933.   }
  934.   *buf_ptr = '\0';
  935.  
  936.   if (pr_fl)
  937.     print(buffer);
  938. }
  939.  
  940.  o2umode(mode)
  941.     char mode;
  942. {
  943.     int ret_mode=0;
  944.  
  945.     if (mode & S_IFDIR)
  946.         ret_mode |= 040000;
  947.     if (mode & S_IREAD)
  948.         ret_mode |= 0400;
  949.     if (mode & S_IWRITE)
  950.         ret_mode |= 0200;
  951.     if (mode & S_IEXEC)
  952.         ret_mode |= 0100;
  953.     if (mode & S_IOREAD)
  954.         ret_mode |= 04;
  955.     if (mode & S_IOWRITE)
  956.         ret_mode |= 02;
  957.     if (mode & S_IOEXEC)
  958.         ret_mode |= 01;
  959.  
  960.     return(ret_mode);
  961. }
  962.  
  963.  u29mode(mode)
  964.     int mode;
  965. {
  966.     int ret_mode=0;
  967.  
  968.     strcpy(modestr,"-----------");
  969.  
  970.     if (mode & 040000) {
  971.         ret_mode  |= S_IFDIR;
  972.         modestr[0] = 'd';
  973.     }
  974.  
  975.     if (mode & 0400) {
  976.         ret_mode  |= S_IREAD;
  977.         modestr[1] = 'r';
  978.     }
  979.  
  980.     if (mode & 0200) {
  981.         ret_mode  |= S_IWRITE;
  982.         modestr[2] = 'w';
  983.     }
  984.  
  985.     if (mode & 0100) {
  986.         ret_mode  |= S_IEXEC;
  987.         modestr[3] = 'x';
  988.     }
  989.  
  990.     if (mode & 04) {
  991.         ret_mode  |= S_IOREAD;
  992.         modestr[7] = 'r';
  993.     }
  994.  
  995.     if (mode & 02) {
  996.         ret_mode  |= S_IOWRITE;
  997.         modestr[8] = 'w';
  998.     }
  999.  
  1000.     if (mode & 01) {
  1001.         ret_mode  |= S_IOEXEC;
  1002.         modestr[9] = 'x';
  1003.     }
  1004.  
  1005.     return(ret_mode);
  1006. }
  1007.  
  1008. char *atime(clock)
  1009.     long clock;
  1010. {
  1011.     static char buf[26];
  1012.     int i;
  1013.  
  1014.     strcpy(buf,ctime(&clock));
  1015.  
  1016.     for (i=4; i< 16; i++)
  1017.         buf[i-4] = buf[i];
  1018.     buf[12] = ' ';
  1019.  
  1020.     for (i=20; i<24; i++)
  1021.         buf[i-7] = buf[i];
  1022.     buf[17] = 0;
  1023.  
  1024.     return(buf);
  1025. }
  1026.  
  1027. char **match(fpt,name)
  1028.     register struct files *fpt;
  1029.     register char *name;
  1030. {
  1031.  
  1032.   while (fpt->name) {
  1033. #ifdef OSK
  1034.     if (!_cmpnam(name,fpt->name,strlen(fpt->name))) {
  1035. #else
  1036.     if (patmatch(fpt->name,name,1)) {
  1037. #endif
  1038.        return(fpt->name);
  1039.     }
  1040.     fpt = fpt->next;
  1041.   }
  1042.   return(NULL);
  1043. }
  1044.  
  1045. #ifdef OSK
  1046. u2otime(om,um)
  1047. struct sgtbuf *om;
  1048. struct tm     *um;
  1049. {
  1050.   om->t_year = um->tm_year;
  1051.   om->t_month = um->tm_mon+1;
  1052.   om->t_day = um->tm_mday;
  1053.   om->t_hour = um->tm_hour;
  1054.   om->t_minute = um->tm_min;
  1055.   om->t_second = um->tm_sec;
  1056. }
  1057.  
  1058. long o2utime(om)
  1059. struct sgtbuf *om;
  1060. {
  1061. struct tm um;
  1062.  
  1063.   um.tm_year = om->t_year;
  1064.   um.tm_mon = om->t_month-1;
  1065.   um.tm_mday = om->t_day;
  1066.   um.tm_hour = om->t_hour;
  1067.   um.tm_min = om->t_minute;
  1068.   um.tm_sec = om->t_second;
  1069.   return mktime(&um);
  1070. }
  1071. #endif
  1072.