home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume07 / pdtar < prev    next >
Encoding:
Text File  |  1988-09-11  |  84.3 KB  |  3,307 lines

  1. Subject:  v07i088:  Public-domain TAR program
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: ihnp4!hoptoad!gnu (John Gilmore)
  6. Mod.sources: Volume 7, Issue 88
  7. Archive-name: pdtar
  8.  
  9. ----------CUT HERE----------
  10. : To unbundle, sh this file
  11. echo README 1>&2
  12. cat >README <<'@@@ Fin de README'
  13. This is a public domain tar(1) replacement.  It implements the 'c',
  14. 'x', and 't' commands of Unix tar, and many of the options.  It creates
  15. P1003 "Unix Standard" [draft 6] tapes by default, and can read and
  16. write both old and new formats.  It can decompress tar archives when
  17. reading them from disk files (using the 'z' option), but cannot do so
  18. when writing, or when reading from a tape drive.  Its verbose output
  19. looks more like "ls -l" than the Unix tar, and even lines up the
  20. columns.  It is a little better at reading damaged tapes than Unix tar.
  21.  
  22. It is designed to be a lot more efficient than the standard Unix tar;
  23. it does as little bcopy-ing as possible, and does file I/O in large
  24. blocks.  On the other hand, it has not been timed or performance-tuned;
  25. it's just *designed* to be faster.
  26.  
  27. On the Sun, the tar archives it creates under the 'old' option are
  28. byte-for-byte the same as those created by /bin/tar, except the trash
  29. at the end of each file and at the end of the archive.
  30.  
  31. It was written and initially debugged on a Sun Workstation running
  32. 4.2BSD.  It has been run on Xenix, Unisoft, Vax 4.2BSD, V7, and USG
  33. systems.  I'm interested in finding people who will port it to other
  34. types of (Unix and non-Unix) systems, use it, and send back the
  35. changes; and people who will add the obscure tar options that they
  36. happen to use and I don't.  In particular, VMS, MSDOS, Mac, Atari and
  37. Amiga versions would be handy.
  38.  
  39. It still has a number of loose ends, marked by "FIXME" comments in the
  40. source.  For example, it does not chown() extracted files.  Fixes to
  41. these things are also welcome.
  42.  
  43. I am the author of all the code in this program.  I hereby place it in
  44. the public domain.  If you modify it, or port it to another system,
  45. please send me back a copy, so I can keep a master source.
  46.  
  47.     John Gilmore
  48.     Nebula Consultants
  49.     1504 Golden Gate Ave.
  50.     San Francisco, California, USA  94115
  51.     +1 415 931 4667        voice
  52.     hoptoad!gnu        data
  53.     jgilmore@lll-crg.arpa    data
  54. Hoptoad talks to sun, ptsfa, well, lll-crg, ihnp4, cbosgd, ucsfcgl, pyramid.
  55.  
  56. @(#)README 1.5    86/10/29
  57. @@@ Fin de README
  58. echo PORTING 1>&2
  59. cat >PORTING <<'@@@ Fin de PORTING'
  60.         Porting hints for public domain tar
  61.           John Gilmore, ihnp4!hoptoad!gnu
  62.              @(#)PORTING 1.5    86/10/29
  63.  
  64. The Makefile should be edited to comment out all the undesired
  65. versions, and create the following configuration lines for the system
  66. you are compiling it on:
  67.  
  68. DEFS = the proper #define's to conditionally compile for
  69. your system.
  70. LIBS = the system libraries and/or object modules to link
  71. with the program.
  72. LINTFLAGS = a good strong way to invoke 'lint' on your system.
  73. DEF_AR_FILE = the name of the default archive file on your system.
  74. It should be enclosed in quoted quotes, e.g. \"/dev/foo\" .
  75. DEFBLOCKING = the default blocking factor on your system.
  76.  
  77. A copy of "getopt", the standard argument parser, is required.  It's in
  78. libc on Missed'em V systems and 4.3BSD; on most other systems, you'll
  79. need a copy of a public domain getopt, available through mod.sources
  80. or the AT&T Toolchest if you can't find it elsewhere.
  81.  
  82. A copy of the Berkeley directory access routines is also required.
  83. These are in libc and <sys/dir.h> on Berkeley systems.  A public domain
  84. version is available through mod.sources.  There is an #include you
  85. have to change in create.c for this, to set the name of the include
  86. file you have.  Some systems have the include file in <sys/ndir.h>.
  87. You'll have to find it on your system, or get the public domain one
  88. and place it somewhere.
  89.  
  90. Grep for FIXME to find places that aren't finished or which have
  91. portability problems.  Also see the file TODO.
  92. @@@ Fin de PORTING
  93. echo Makefile 1>&2
  94. cat >Makefile <<'@@@ Fin de Makefile'
  95. # Makefile for public domain tar program.
  96. # @(#)Makefile 1.13    86/10/29
  97.  
  98. # Berserkeley version
  99. DEFS = -DBSD42
  100. LIBS = 
  101. LINTFLAGS = -abchx
  102. DEF_AR_FILE = \"/dev/rmt8\"
  103. DEFBLOCKING = 20
  104.  
  105. # USG version
  106. #DEFS = -DUSG
  107. #LIBS = -lndir
  108. #LINTFLAGS = -bx
  109. #DEF_AR_FILE = \"/dev/rmt8\"
  110. #DEFBLOCKING = 20
  111.  
  112. # UniSoft's Uniplus SVR2 with NFS
  113. #DEFS = -DUSG -DUNIPLUS -DNFS -DSVR2
  114. #LIBS = -lndir
  115. #LINTFLAGS = -bx
  116. #DEF_AR_FILE = \"/dev/rmt8\"
  117. #DEFBLOCKING = 20
  118.  
  119. # V7 version
  120. #DEFS = -DV7 -Dvoid=int
  121. #LIBS = -lndir
  122. #LINTFLAGS = -abchx
  123. #DEF_AR_FILE = \"/dev/rmt8\"
  124. #DEFBLOCKING = 20
  125.  
  126. CFLAGS = $(COPTS) $(DEFS) \
  127.     -DDEF_AR_FILE=$(DEF_AR_FILE) \
  128.     -DDEFBLOCKING=$(DEFBLOCKING)
  129. # next line for Debugging
  130. COPTS = -g
  131. # next line for Production
  132. #COPTS = -O
  133.  
  134. # Add things here like getopt, readdir, etc that aren't in your
  135. # standard libraries.
  136. SUBSRC=    
  137. SUBOBJ=    
  138.  
  139. SRCS =    tar.c create.c extract.c buffer.c getoldopt.c list.c names.c \
  140.     port.c $(SUBSRC)
  141. OBJS =     tar.o create.o extract.o buffer.o getoldopt.o list.o names.o \
  142.     port.o $(SUBOBJ)
  143. AUX =    README PORTING Makefile TODO tar.1 tar.5 tar.h port.h
  144.  
  145. tar:    $(OBJS)
  146.     cc -o tar $(COPTS) $(OBJS) $(LIBS)
  147.  
  148. lint:    $(SRCS)
  149.     lint $(LINTFLAGS) $(CFLAGS) $(SRCS)
  150.  
  151. clean:
  152.     rm -f errs *.o tar
  153.  
  154. tar.shar: $(SRCS) $(AUX)
  155.     shar >tar.shar $(AUX) $(SRCS)
  156.  
  157. tar.tar.Z: $(SRCS) $(AUX)
  158.     /bin/tar cf - $(AUX) $(SRCS) | compress -v >tar.tar.Z
  159.  
  160. $(OBJS): tar.h port.h
  161. @@@ Fin de Makefile
  162. echo TODO 1>&2
  163. cat >TODO <<'@@@ Fin de TODO'
  164. @(#) TODO 1.6 86/10/29
  165.  
  166. Install new mkdir from the net for non-Berkeley systems.
  167.  
  168. Look at SUID, SGID; look at -p and -m options.  (test them).
  169.  
  170. Handle owner/group on extraction.
  171.  
  172. creation of links and symlinks doesn't follow the -k (f_keep) guidelines;
  173. if the file already exists, it is not replaced, even though no -k.
  174.  
  175. Check stderr and stdout for errors after writing, and quit if so.
  176.  
  177. Compression option to automatically pipe thru compress (both input&output).
  178. (Need a 3rd process to reblock compress's output for output case, and when
  179. reading from tape drives.)
  180.  
  181. Preliminary design of Multifile option to handle EOFs on input and output.
  182. Multifile can just write EOF when it hits end of archive, and ask for
  183. archive to be changed.  Start off 2nd archive medium with odd header
  184. block, duplicating original, but with offset to start of data spec'd.
  185. Reading such a header causes tar non-'M' to complain while extracting
  186. (but to seek there and do it anyway!)  Big win -- this works on
  187. cartridge tapes, should work on floppies, might work on magtape.
  188. It would encourage the *&%#$ systems programmers to fix their drivers, too!
  189.  
  190. Profile it and see where the time, call counts, etc are going.
  191.  
  192. Test reading compressed tapes with odd blocksizes.
  193. (real tape drives, that is...)
  194. (may need buffer proc no matter what.)
  195.  
  196. Fix directory timestamps after inserting files into them.  Wait til next
  197. file that's not in the directory.  Need a stack of them.
  198.  
  199. Add option to delete N matching(?) chars from the front of a file to
  200. be extracted/listed.  Great for reading tapes written with names starting
  201. from "/"...
  202.  
  203. Option to seek the input file (in skip_file) rather than reading
  204. and tossing it?  (Could just jump in buffer if stuff is in core.)
  205. Could misalign archive reads versus filesys and slow it down, who knows?
  206.  
  207. Add -C option for creating from odd directories a la 4.2BSD?
  208.  
  209. Break out odd bits of code into separate support modules.
  210.  
  211. Add the r, u, X, l, F, C, and digit options of Unix tar.
  212. @@@ Fin de TODO
  213. echo tar.1 1>&2
  214. cat >tar.1 <<'@@@ Fin de tar.1'
  215. .TH TAR 1 "31 October 1986"
  216. .SH NAME
  217. tar \- tape (or other media) file archiver
  218. .SH SYNOPSIS
  219. \fBtar\fP \-[\fBBcDhikmopstvxzZ\fP]
  220. [\fB\-b\fP \fIN\fP]
  221. [\fB\-f\fP \fIF\fP]
  222. [\fB\-T\fP \fIF\fP]
  223. [ \fIfilename\fP\| .\|.\|.  ]
  224. .SH DESCRIPTION
  225. \fItar\fP provides a way to store many files into a single archive,
  226. which can be kept in another Unix file, stored on an I/O device
  227. such as tape, floppy, cartridge, or disk, or piped to another program.
  228. It is useful for making backup copies, or for packaging up a set of
  229. files to move them to another system.
  230. .LP
  231. \fItar\fP has existed since Version 7 Unix with very little change.
  232. It has been proposed as the standard format for interchange of files
  233. among systems that conform to the P1003 ``Portable Operating System''
  234. standard.
  235. .LP
  236. This version of \fItar\fP supports the extensions which
  237. were proposed in the P1003 draft standards, including owner and group
  238. names, and support for named pipes, fifos, and block and character devices.
  239. .LP
  240. When reading an archive, this version of \fItar\fP continues after
  241. finding an error.  Previous versions required the `i' option to ignore
  242. checksum errors.
  243. .SH OPTIONS
  244. \fItar\fP options can be specified in either of two ways.  The usual
  245. Unix conventions can be used: each option is preceded by `\-'; arguments
  246. directly follow each option; multiple options can be combined behind one `\-'
  247. as long as they take no arguments.  For compatability with the Unix
  248. \fItar\fP program, the options may also be specified as ``keyletters,''
  249. wherein all the option letters occur in the first argument to \fItar\fP,
  250. with no `\-', and their arguments, if any, occur in the second, third, ...
  251. arguments.  Examples:
  252. .LP
  253. Normal:  tar -f arcname -cv file1 file2
  254. .LP
  255. Old:  tar fcv arcname file1 file2
  256. .LP
  257. At least one of the \fB\-c\fP, \fB\-t\fP, or \fB\-x\fP options
  258. must be included.  The rest are optional.
  259. .LP
  260. Files to be operated upon are specified by a list of file names, which
  261. follows the option specifications (or can be read from a file by the
  262. \fB\-T\fP option).  Specifying a directory name causes that directory
  263. and all the files it contains to be (recursively) processed.  In general,
  264. specifying full path names when creating an archive is a bad idea,
  265. since when the files are
  266. extracted, they will have to be extracted into exactly where they were
  267. dumped from.  Instead, \fIcd\fP to the
  268. root directory and use relative file names.
  269. .IP "\fB\-b\fP \fIN\fP"
  270. Specify a blocking factor for the archive.  The block size will be
  271. \fIN\fP x 512 bytes.  Larger blocks typically run faster and let you
  272. fit more data on a tape.  The default blocking factor is set when
  273. \fItar\fP is compiled, and is typically 20.  There is no limit to the
  274. maximum block size, as long as enough memory can be allocated for it,
  275. and as long as the device containing the archive can read or write
  276. that block size.
  277. .IP \fB\-B\fP
  278. When reading an archive, reblock it as we read it.
  279. Normally, \fItar\fP reads each
  280. block with a single \fIread(2)\fP system call.  This does not work
  281. when reading from a pipe or network socket under Berkeley Unix.
  282. With this option, it
  283. will do multiple \fIread(2)\fPs until it gets enough data to fill 
  284. the specified block size.  \fB\-B\fP can also be used to speed up
  285. the reading of tapes that were written with small blocking factors,
  286. by specifying a large blocking factor with \fB\-b\fP and having \fItar\fP
  287. read many small blocks into memory before it tries to process them.
  288. .IP \fB\-c\fP
  289. Create an archive from a list of files.
  290. .IP \fB\-D\fP
  291. With each message that \fItar\fP produces, print the record number
  292. within the archive where the message occurred.  This option is especially
  293. useful when reading damaged archives, since it helps to pinpoint the damaged
  294. section.
  295. .IP "\fB\-f\fP \fIF\fP"
  296. Specify the filename of the archive.  If the specified filename is ``\-'',
  297. the archive is read from the standard input or written to the standard output.
  298. If this option is not used,
  299. a default archive name (which was picked when tar was compiled) is used.
  300. The default is normally set to the ``first'' tape drive or other transportable
  301. I/O medium on the system.
  302. .IP \fB\-h\fP
  303. When creating an archive, if a symbolic link is encountered, dump
  304. the file or directory to which it points, rather than
  305. dumping it as a symbolic link.
  306. .IP \fB\-i\fP
  307. When reading an archive, ignore blocks of zeros in the archive.  Normally
  308. a block of zeros indicates the end of the archive,
  309. but in a damaged archive, or one which was
  310. created by appending several archives, this option allows \fItar\fP to 
  311. continue.  It is not on by default because there is garbage written after the
  312. zeroed blocks by the Unix \fItar\fP program.
  313. .IP \fB\-k\fP
  314. When extracting files from an archive, keep existing files, rather than
  315. overwriting them with the version from the archive.
  316. .IP \fB\-m\fP
  317. When extracting files from an archive, set each file's modified timestamp
  318. to the current time, rather than extracting each file's modified
  319. timestamp from the archive.
  320. .IP \fB\-o\fP
  321. When creating an archive, write an old format archive, which does not
  322. include information about directories, pipes, or device files, and 
  323. specifies file ownership by uid's and gid's rather than by
  324. user names and group names.  In most cases, a ``new'' format archive
  325. can be read by an ``old'' tar program without serious trouble, so this
  326. option should seldom be needed.
  327. .IP \fB\-p\fP
  328. When extracting files from an archive, restore them to the same permissions
  329. that they had in the archive.  If \fB\-p\fP is not specified, the current
  330. umask limits the permissions of the extracted files.  See \fIumask(2)\fP.
  331. .IP \fB\-t\fP
  332. List a table of contents of an existing archive.  If file names are
  333. specified, just list files matching the specified names.
  334. .IP \fB\-s\fP
  335. When specifying a list of filenames to be listed
  336. or extracted from an archive,
  337. the \fB\-s\fP flag specifies that the list
  338. is sorted into the same order as the tape.  This allows a large list
  339. to be used, even on small machines, because
  340. the entire list need not be read into memory at once.  Such a sorted
  341. list can easily be created by running ``tar \-t'' on the archive and
  342. editing its output.
  343. .IP "\fB\-T\fP \fIF\fP"
  344. Rather than specifying the file names to operate on as arguments to
  345. the \fItar\fP command, this option specifies that the file names should
  346. be read from the file \fIF\fP, one per line.
  347. If the file name specified is ``\-'',
  348. the list is read from the standard input.
  349. This option, in conjunction with the \fB\-s\fP option,
  350. allows an arbitrarily large list of files to be processed, 
  351. and allows the list to be piped to \fItar\fP.
  352. .IP \fB\-v\fP
  353. Be verbose about the files that are being processed or listed.  Normally,
  354. archive creation or file extraction are silent, and archive listing just
  355. gives file names.  The \fB\-v\fP option causes an ``ls \-l''\-like listing
  356. to be produced.
  357. .IP \fB\-x\fP
  358. Extract files from an existing archive.  If file names are
  359. specified, just extract files matching the specified names, otherwise extract
  360. all the files in the archive.
  361. .IP "\fB\-z\fP or \fB\-Z\fP"
  362. When extracting or listing an archive,
  363. these options specify
  364. that the archive should be decompressed while it is read, using the \-d
  365. option of the \fIcompress(1)\fP program.  The archive itself is not
  366. modified.
  367. .SH "SEE ALSO"
  368. shar(1), tar(5), compress(1), ar(1), arc(1), cpio(1), dump(8), restore(8),
  369. restor(8)
  370. .SH BUGS
  371. The \fBr, u, w, X, l, F, C\fP, and \fIdigit\fP options of Unix \fItar\fP
  372. are not supported.
  373. .LP
  374. It should be possible to create a compressed archive with the \fB\-z\fP option.
  375. .LP
  376. @@@ Fin de tar.1
  377. echo tar.5 1>&2
  378. cat >tar.5 <<'@@@ Fin de tar.5'
  379. .TH TAR 5 "31 October 1986"
  380. .SH NAME
  381. tar \- tape (or other media) archive file format
  382. .SH DESCRIPTION
  383. A ``tar tape'' or file contains a series of records.  Each record contains
  384. TRECORDSIZE bytes (see below).  Although this format may be thought of as
  385. being on magnetic tape, other media are often used.
  386. Each file archived is represented by a header record
  387. which describes the file, followed by zero or more records which give the
  388. contents of the file.  At the end of the archive file there may be a record
  389. filled with binary zeros as an end-of-file indicator.  A conforming
  390. system must write a record of zeros at the end, but must not assume that
  391. an end-of-file record exists when reading an archive.
  392.  
  393. The records may be blocked for physical I/O operations.  Each block of
  394. \fIN\fP records (where \fIN\fP is set by the \fB\-b\fP option to \fItar\fP)
  395. is written with a single write() operation.  On
  396. magnetic tapes, the result of such a write is a single tape record.
  397. When writing an archive, the last block of records shall be written
  398. at the full size, with records after the zero record containing
  399. undefined data.  When reading an archive, a confirming system shall
  400. properly handle an archive whose last block is shorter than the rest.
  401.  
  402. The header record is defined in the header file <tar.h> as follows:
  403. .nf
  404. .sp .5v
  405. .DT
  406. /*
  407.  * Standard Archive Format - Standard TAR - USTAR
  408.  */
  409. #define    RECORDSIZE    512
  410. #define    NAMSIZ    100
  411. #define    TUNMLEN    32
  412. #define    TGNMLEN    32
  413.  
  414. union record {
  415.     char        charptr[RECORDSIZE];
  416.     struct header {
  417.         char    name[NAMSIZ];
  418.         char    mode[8];
  419.         char    uid[8];
  420.         char    gid[8];
  421.         char    size[12];
  422.         char    mtime[12];
  423.         char    chksum[8];
  424.         char    linkflag;
  425.         char    linkname[NAMSIZ];
  426.         char    magic[8];
  427.         char    uname[TUNMLEN];
  428.         char    gname[TGNMLEN];
  429.         char    devmajor[8];
  430.         char    devminor[8];
  431.     } header;
  432. };
  433.  
  434. /* The checksum field is filled with this while the checksum is computed. */
  435. #define    CHKBLANKS    "        "        /* 8 blanks, no null */
  436.  
  437. /* The magic field is filled with this if uname and gname are valid. */
  438. #define    TMAGIC    "ustar  "        /* 7 chars and a null */
  439.  
  440. /* The linkflag defines the type of file */
  441. #define    LF_OLDNORMAL '\\0'        /* Normal disk file, Unix compatible */
  442. #define    LF_NORMAL    '0'        /* Normal disk file */
  443. #define    LF_LINK    '1'        /* Link to previously dumped file */
  444. #define    LF_SYMLINK    '2'        /* Symbolic link */
  445. #define    LF_CHR    '3'        /* Character special file */
  446. #define    LF_BLK    '4'        /* Block special file */
  447. #define    LF_DIR        '5'        /* Directory */
  448. #define    LF_FIFO    '6'        /* FIFO special file */
  449. #define    LF_CONTIG    '7'        /* Contiguous file */
  450. /* Further link types may be defined later. */
  451.  
  452. /* Bits used in the mode field - values in octal */
  453. #define    TSUID        04000        /* Set UID on execution */
  454. #define    TSGID        02000        /* Set GID on execution */
  455. #define    TSVTX        01000        /* Save text (sticky bit) */
  456.  
  457. /* File permissions */
  458. #define    TUREAD    00400        /* read by owner */
  459. #define    TUWRITE    00200        /* write by owner */
  460. #define    TUEXEC    00100        /* execute/search by owner */
  461. #define    TGREAD    00040        /* read by group */
  462. #define    TGWRITE    00020        /* write by group */
  463. #define    TGEXEC    00010        /* execute/search by group */
  464. #define    TOREAD    00004        /* read by other */
  465. #define    TOWRITE    00002        /* write by other */
  466. #define    TOEXEC    00001        /* execute/search by other */
  467. .fi
  468. .LP
  469. All characters in header records
  470. are represented using 8-bit characters in the local
  471. variant of ASCII.
  472. Each field within the structure is contiguous; that is, there is
  473. no padding used within the structure.  Each character on the archive medium
  474. is stored contiguously.
  475.  
  476. Bytes representing the contents of files (after the header record
  477. of each file) are not translated in any way and
  478. are not constrained to represent characters or to be in any character set.
  479. The \fItar\fP(5) format does not distinguish text files from binary
  480. files, and no translation of file contents should be performed.
  481.  
  482. The fields \fIname, linkname, magic, uname\fP, and \fIgname\fP are
  483. null-terminated
  484. character strings.  All other fields are zero-filled octal numbers in
  485. ASCII.  Each numeric field (of width \fIw\fP) contains \fIw\fP-2 digits, a space, and
  486. a null, except \fIsize\fP and \fImtime\fP,
  487. which do not contain the trailing null.
  488.  
  489. The \fIname\fP field is the pathname of the file, with directory names
  490. (if any) preceding the file name, separated by slashes.
  491.  
  492. The \fImode\fP field provides nine bits specifying file permissions and three
  493. bits to specify the Set UID, Set GID and Save Text (TSVTX) modes.  Values
  494. for these bits are defined above.  When special permissions are required
  495. to create a file with a given mode, and the user restoring files from the
  496. archive does not hold such permissions, the mode bit(s) specifying those
  497. special permissions are ignored.  Modes which are not supported by the
  498. operating system restoring files from the archive will be ignored.
  499. Unsupported modes should be faked up when creating an archive; e.g.
  500. the group permission could be copied from the `other' permission.
  501.  
  502. The \fIuid\fP and \fIgid\fP fields are the user and group ID of the file owners,
  503. respectively.
  504.  
  505. The \fIsize\fP field is the size of the file in bytes; linked files are archived
  506. with this field specified as zero.
  507.  
  508. The \fImtime\fP field is the modification time of the file at the time it was
  509. archived.  It is the ASCII representation of the octal value of the
  510. last time the file was modified, represented as in integer number of
  511. seconds since January 1, 1970, 00:00 Coordinated Universal Time.
  512.  
  513. The \fIchksum\fP field is the ASCII representaion of the octal value of the
  514. simple sum of all bytes in the header record.  Each 8-bit byte in the
  515. header is treated as an unsigned value.  These values are added to an
  516. unsigned integer, initialized to zero, the precision of which shall be no
  517. less than seventeen bits.  When calculating the checksum, the \fIchksum\fP
  518. field is treated as if it were all blanks.
  519.  
  520. The \fItypeflag\fP field specifies the type of file archived.  If a particular
  521. implementation does not recognize or permit the specified type, the file
  522. will be extracted as if it were a regular file.  As this action occurs,
  523. \fItar\fP issues a warning to the standard error.
  524. .IP "LF_NORMAL or LF_OLDNORMAL"
  525. represents a regular file.
  526. For backward compatibility, a \fItypeflag\fP value of LF_OLDNORMAL
  527. should be silently recognized as a regular file.  New archives should
  528. be created using LF_NORMAL.
  529. Also, for backward
  530. compatability, \fItar\fP treats a regular file whose name ends
  531. with a slash as a directory.
  532. .IP LF_LINK
  533. represents a file linked to another file, of any type,
  534. previously archived.  Such files are identified (in Unix) by each file
  535. having the same device and inode number.  The linked-to
  536. name is specified in the \fIlinkname\fP field with a trailing null.
  537. .IP LF_SYMLINK
  538. represents a symbolic link to another file.  The linked-to
  539. name is specified in the \fIlinkname\fP field with a trailing null.
  540. .IP "LF_CHR or LF_BLK"
  541. represent character special files and block
  542. special files respectively.
  543. In this case the \fIdevmajor\fP and \fIdevminor\fP
  544. fields will contain the
  545. major and minor device numbers respectively.  Operating
  546. systems may map the device specifications to their own local
  547. specification, or may ignore the entry.
  548. .IP LF_DIR
  549. specifies a directory or sub-directory.  The directory name
  550. in the \fIname\fP field should end with a slash.
  551. On systems where
  552. disk allocation is performed on a directory basis the \fIsize\fP
  553. field will contain the maximum number of bytes (which may be
  554. rounded to the nearest disk block allocation unit) which the
  555. directory may hold.  A \fIsize\fP field of zero indicates no such
  556. limiting.  Systems which do not support limiting in this
  557. manner should ignore the \fIsize\fP field.
  558. .IP LF_FIFO
  559. specifies a FIFO special file.  Note that the archiving of
  560. a FIFO file archives the existence of this file and not its
  561. contents.
  562. .IP LF_CONTIG
  563. specifies a contiguous file, which is the same as a normal
  564. file except that, in operating systems which support it,
  565. all its space is allocated contiguously on the disk.  Operating
  566. systems which do not allow contiguous allocation should silently treat
  567. this type as a normal file.
  568. .IP "`A' \- `Z'"
  569. are reserved for custom implementations.  None are used by this
  570. version of the \fItar\fP program.
  571. .IP \fIother\fP
  572. values are reserved for specification in future revisions of the
  573. P1003 standard, and should not be used by any \fItar\fP program.
  574. .LP
  575. The \fImagic\fP field indicates that this archive was output in the P1003
  576. archive format.  If this field contains TMAGIC, then the
  577. \fIuname\fP and \fIgname\fP
  578. fields will contain the ASCII representation of the owner and group of the
  579. file respectively.  If found, the user and group ID represented by these
  580. names
  581. will be used rather than the values contained
  582. within the \fIuid\fP and \fIgid\fP fields.
  583. User names longer than TUNMLEN-1 or group
  584. names longer than TGNMLEN-1 characters will be truncated.
  585. .SH "SEE ALSO"
  586. tar(1), ar(5), cpio(5)
  587. .SH BUGS
  588. Names or link names longer than NAMSIZ-1 characters cannot be archived.
  589.  
  590. This format does not address multi-volume archives.
  591. .SH NOTES
  592. This manual page was adapted by John Gilmore
  593. from Draft 6 of the P1003 specification
  594. @@@ Fin de tar.5
  595. echo tar.h 1>&2
  596. cat >tar.h <<'@@@ Fin de tar.h'
  597. /*
  598.  * Header file for public domain tar (tape archive) program.
  599.  *
  600.  * @(#)tar.h 1.20 86/10/29    Public Domain.
  601.  *
  602.  * Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  603.  */
  604.  
  605. /*
  606.  * Kludge for handling systems that can't cope with multiple
  607.  * external definitions of a variable.  In ONE routine (tar.c),
  608.  * we #define TAR_EXTERN to null; here, we set it to "extern" if
  609.  * it is not already set.
  610.  */
  611. #ifndef TAR_EXTERN
  612. #define TAR_EXTERN extern
  613. #endif
  614.  
  615. /*
  616.  * Header block on tape.
  617.  *
  618.  * I'm going to use traditional DP naming conventions here.
  619.  * A "block" is a big chunk of stuff that we do I/O on.
  620.  * A "record" is a piece of info that we care about.
  621.  * Typically many "record"s fit into a "block".
  622.  */
  623. #define    RECORDSIZE    512
  624. #define    NAMSIZ    100
  625. #define    TUNMLEN    32
  626. #define    TGNMLEN    32
  627.  
  628. union record {
  629.     char        charptr[RECORDSIZE];
  630.     struct header {
  631.         char    name[NAMSIZ];
  632.         char    mode[8];
  633.         char    uid[8];
  634.         char    gid[8];
  635.         char    size[12];
  636.         char    mtime[12];
  637.         char    chksum[8];
  638.         char    linkflag;
  639.         char    linkname[NAMSIZ];
  640.         char    magic[8];
  641.         char    uname[TUNMLEN];
  642.         char    gname[TGNMLEN];
  643.         char    devmajor[8];
  644.         char    devminor[8];
  645.     } header;
  646. };
  647.  
  648. /* The checksum field is filled with this while the checksum is computed. */
  649. #define    CHKBLANKS    "        "    /* 8 blanks, no null */
  650.  
  651. /* The magic field is filled with this if uname and gname are valid. */
  652. #define    TMAGIC        "ustar  "    /* 7 chars and a null */
  653.  
  654. /* The linkflag defines the type of file */
  655. #define    LF_OLDNORMAL    '\0'        /* Normal disk file, Unix compat */
  656. #define    LF_NORMAL    '0'        /* Normal disk file */
  657. #define    LF_LINK        '1'        /* Link to previously dumped file */
  658. #define    LF_SYMLINK    '2'        /* Symbolic link */
  659. #define    LF_CHR        '3'        /* Character special file */
  660. #define    LF_BLK        '4'        /* Block special file */
  661. #define    LF_DIR        '5'        /* Directory */
  662. #define    LF_FIFO        '6'        /* FIFO special file */
  663. #define    LF_CONTIG    '7'        /* Contiguous file */
  664. /* Further link types may be defined later. */
  665.  
  666. /*
  667.  * Exit codes from the "tar" program
  668.  */
  669. #define    EX_SUCCESS    0        /* success! */
  670. #define    EX_ARGSBAD    1        /* invalid args */
  671. #define    EX_BADFILE    2        /* invalid filename */
  672. #define    EX_BADARCH    3        /* bad archive */
  673. #define    EX_SYSTEM    4        /* system gave unexpected error */
  674.  
  675.  
  676. /*
  677.  * Global variables
  678.  */
  679. TAR_EXTERN union record    *ar_block;    /* Start of block of archive */
  680. TAR_EXTERN union record    *ar_record;    /* Current record of archive */
  681. TAR_EXTERN union record    *ar_last;    /* Last+1 record of archive block */
  682. TAR_EXTERN char        ar_reading;    /* 0 writing, !0 reading archive */
  683. TAR_EXTERN int        blocking;    /* Size of each block, in records */
  684. TAR_EXTERN int        blocksize;    /* Size of each block, in bytes */
  685. TAR_EXTERN char        *ar_file;    /* File containing archive */
  686. TAR_EXTERN char        *name_file;    /* File containing names to work on */
  687. TAR_EXTERN char        *tar;        /* Name of this program */
  688.  
  689. /*
  690.  * Flags from the command line
  691.  */
  692. TAR_EXTERN char    f_reblock;        /* -B */
  693. TAR_EXTERN char    f_create;        /* -c */
  694. TAR_EXTERN char    f_debug;        /* -d */
  695. TAR_EXTERN char    f_sayblock;        /* -D */
  696. TAR_EXTERN char    f_follow_links;        /* -h */
  697. TAR_EXTERN char    f_ignorez;        /* -i */
  698. TAR_EXTERN char    f_keep;            /* -k */
  699. TAR_EXTERN char    f_modified;        /* -m */
  700. TAR_EXTERN char    f_oldarch;        /* -o */
  701. TAR_EXTERN char    f_use_protection;    /* -p */
  702. TAR_EXTERN char    f_sorted_names;        /* -s */
  703. TAR_EXTERN char    f_list;            /* -t */
  704. TAR_EXTERN char    f_namefile;        /* -T */
  705. TAR_EXTERN char    f_verbose;        /* -v */
  706. TAR_EXTERN char    f_extract;        /* -x */
  707. TAR_EXTERN char    f_compress;        /* -z */
  708.  
  709. /*
  710.  * We now default to Unix Standard format rather than 4.2BSD tar format.
  711.  * The code can actually produce all three:
  712.  *    f_standard    ANSI standard
  713.  *    f_oldarch    V7
  714.  *    neither        4.2BSD
  715.  * but we don't bother, since 4.2BSD can read ANSI standard format anyway.
  716.  * The only advantage to the "neither" option is that we can cmp(1) our
  717.  * output to the output of 4.2BSD tar, for debugging.
  718.  */
  719. #define        f_standard        (!f_oldarch)
  720.  
  721. /*
  722.  * Structure for keeping track of filenames and lists thereof.
  723.  */
  724. struct name {
  725.     struct name    *next;
  726.     short        length;
  727.     char        found;
  728.     char        name[NAMSIZ+1];
  729. };
  730.  
  731. TAR_EXTERN struct name    *namelist;    /* Points to first name in list */
  732. TAR_EXTERN struct name    *namelast;    /* Points to last name in list */
  733.  
  734. TAR_EXTERN int        archive;    /* File descriptor for archive file */
  735. TAR_EXTERN int        errors;        /* # of files in error */
  736.  
  737. /*
  738.  *
  739.  * Due to the next struct declaration, each routine that includes
  740.  * "tar.h" must also include <sys/types.h>.  I tried to make it automatic,
  741.  * but System V has no defines in <sys/types.h>, so there is no way of
  742.  * knowing when it has been included.  In addition, it cannot be included
  743.  * twice, but must be included exactly once.  Argghh!
  744.  *
  745.  * Thanks, typedef.  Thanks, USG.
  746.  */
  747. struct link {
  748.     struct link    *next;
  749.     dev_t        dev;
  750.     ino_t        ino;
  751.     short        linkcount;
  752.     char        name[NAMSIZ+1];
  753. };
  754.  
  755. TAR_EXTERN struct link    *linklist;    /* Points to first link in list */
  756.  
  757.  
  758. /*
  759.  * Error recovery stuff
  760.  */
  761. TAR_EXTERN char        read_error_flag;
  762.  
  763.  
  764. /*
  765.  * Declarations of functions available to the world.
  766.  */
  767. union record *findrec();
  768. void userec();
  769. union record *endofrecs();
  770. void anno();
  771. #define     annorec(stream, msg)    anno(stream, msg, 0)    /* Cur rec */
  772. #define    annofile(stream, msg)    anno(stream, msg, 1)    /* Saved rec */
  773. @@@ Fin de tar.h
  774. echo port.h 1>&2
  775. cat >port.h <<'@@@ Fin de port.h'
  776. /*
  777.  * Portability declarations for public domain tar.
  778.  *
  779.  * @(#)port.h 1.1    86/03/11    Public Domain by John Gilmore, 1986
  780.  */
  781.  
  782. /*
  783.  * Everybody does wait() differently.  There seem to be no definitions
  784.  * for this in V7 (e.g. you are supposed to shift and mask things out
  785.  * using constant shifts and masks.)  So fuck 'em all -- my own non
  786.  * standard but portable macros.  Don't change to a "union wait"
  787.  * based approach -- the ordering of the elements of the struct 
  788.  * depends on the byte-sex of the machine.  Foo!
  789.  */
  790. #define    TERM_SIGNAL(status)    ((status) & 0x7F)
  791. #define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  792. #define TERM_VALUE(status)    ((status) >> 8)
  793.  
  794.  
  795. @@@ Fin de port.h
  796. echo tar.c 1>&2
  797. cat >tar.c <<'@@@ Fin de tar.c'
  798. /*
  799.  * A public domain tar(1) program.
  800.  * 
  801.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  802.  *
  803.  * @(#)tar.c 1.21 10/29/86 Public Domain - gnu
  804.  */
  805.  
  806. #include <stdio.h>
  807. #include <sys/types.h>        /* Needed for typedefs in tar.h */
  808.  
  809. extern char     *malloc();
  810. extern char    *strncpy();
  811. extern char    *optarg;    /* Pointer to argument */
  812. extern int    optind;        /* Global argv index from getopt */
  813.  
  814. /*
  815.  * The following causes "tar.h" to produce definitions of all the
  816.  * global variables, rather than just "extern" declarations of them.
  817.  */
  818. #define TAR_EXTERN /**/
  819. #include "tar.h"
  820.  
  821. /*
  822.  * We should use a conversion routine that does reasonable error
  823.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  824.  */
  825. #define intconv    atoi
  826. extern int    getoldopt();
  827. extern void    read_and();
  828. extern void    list_archive();
  829. extern void    extract_archive();
  830. extern void    create_archive();
  831.  
  832. static FILE    *namef;        /* File to read names from */
  833. static char    **n_argv;    /* Argv used by name routines */
  834. static int    n_argc;    /* Argc used by name routines */
  835.                 /* They also use "optind" from getopt(). */
  836.  
  837. void    describe();
  838.  
  839.  
  840. /*
  841.  * Main routine for tar.
  842.  */
  843. main(argc, argv)
  844.     int    argc;
  845.     char    **argv;
  846. {
  847.  
  848.     /* Uncomment this message in particularly buggy versions...
  849.     fprintf(stderr,
  850.      "tar: You are running an experimental PD tar, maybe use /bin/tar.\n");
  851.      */
  852.  
  853.     tar = "tar";        /* Set program name */
  854.  
  855.     options(argc, argv);
  856.  
  857.     name_init(argc, argv);
  858.  
  859.     if (f_create) {
  860.         if (f_extract || f_list) goto dupflags;
  861.         create_archive();
  862.     } else if (f_extract) {
  863.         if (f_list) goto dupflags;
  864.         read_and(extract_archive);
  865.     } else if (f_list) {
  866.         read_and(list_archive);
  867.     } else {
  868. dupflags:
  869.         fprintf (stderr,
  870. "tar: you must specify exactly one of the c, t, or x options\n");
  871.         describe();
  872.         exit(EX_ARGSBAD);
  873.     }
  874.     exit(0);
  875. }
  876.  
  877.  
  878. /*
  879.  * Parse the options for tar.
  880.  */
  881. int
  882. options(argc, argv)
  883.     int    argc;
  884.     char    **argv;
  885. {
  886.     register int    c;        /* Option letter */
  887.  
  888.     /* Set default option values */
  889.     blocking = DEFBLOCKING;        /* From Makefile */
  890.     ar_file = DEF_AR_FILE;        /* From Makefile */
  891.  
  892.     /* Parse options */
  893.     while ((c = getoldopt(argc, argv, "b:BcdDf:hikmopstT:vxzZ")
  894.         ) != EOF) {
  895.         switch (c) {
  896.  
  897.         case 'b':
  898.             blocking = intconv(optarg);
  899.             break;
  900.  
  901.         case 'B':
  902.             f_reblock++;        /* For reading 4.2BSD pipes */
  903.             break;
  904.  
  905.         case 'c':
  906.             f_create++;
  907.             break;
  908.  
  909.         case 'd':
  910.             f_debug++;        /* Debugging code */
  911.             break;            /* Yes, even with dbx */
  912.  
  913.         case 'D':
  914.             f_sayblock++;        /* Print block #s for debug */
  915.             break;            /* of bad tar archives */
  916.  
  917.         case 'f':
  918.             ar_file = optarg;
  919.             break;
  920.  
  921.         case 'h':
  922.             f_follow_links++;    /* follow symbolic links */
  923.             break;
  924.  
  925.         case 'i':
  926.             f_ignorez++;        /* Ignore zero records (eofs) */
  927.             /*
  928.              * This can't be the default, because Unix tar
  929.              * writes two records of zeros, then pads out the
  930.              * block with garbage.
  931.              */
  932.             break;
  933.  
  934.         case 'k':            /* Don't overwrite files */
  935.             f_keep++;
  936.             break;
  937.  
  938.         case 'm':
  939.             f_modified++;
  940.             break;
  941.  
  942.         case 'o':            /* Generate old archive */
  943.             f_oldarch++;
  944.             break;
  945.  
  946.         case 'p':
  947.             f_use_protection++;
  948.             (void)umask(0);        /* Turn off kernel "help" */
  949.             break;
  950.  
  951.         case 's':
  952.             f_sorted_names++;    /* Names to extr are sorted */
  953.             break;
  954.  
  955.         case 't':
  956.             f_list++;
  957.             break;
  958.  
  959.         case 'T':
  960.             name_file = optarg;
  961.             f_namefile++;
  962.             break;
  963.  
  964.         case 'v':
  965.             f_verbose++;
  966.             break;
  967.  
  968.         case 'x':
  969.             f_extract++;
  970.             break;
  971.  
  972.         case 'z':        /* Easy to type */
  973.         case 'Z':        /* Like the filename extension .Z */
  974.             f_compress++;
  975.             break;
  976.  
  977.         case '?':
  978.             describe();
  979.             exit(EX_ARGSBAD);
  980.  
  981.         }
  982.     }
  983.  
  984.     blocksize = blocking * RECORDSIZE;
  985. }
  986.  
  987.  
  988. /* FIXME, describe tar options here */
  989. void
  990. describe()
  991. {
  992.  
  993.     fputs("tar: valid options:\n\
  994. -b N    blocking factor N (block size = Nx512 bytes)\n\
  995. -B    reblock as we read (for reading 4.2BSD pipes)\n\
  996. -c    create an archive\n\
  997. -D    dump record number within archive with each message\n\
  998. -f F    read/write archive from file or device F\n\
  999. -h    don't dump symbolic links; dump the files they point to\n\
  1000. -i    ignore blocks of zeros in the archive, which normally mean EOF\n\
  1001. -k    keep existing files, don't overwrite them from the archive\n\
  1002. -m    don't extract file modified time\n\
  1003. -o    write an old V7 format archive, rather than ANSI [draft 6] format\n\
  1004. -p    do extract all protection information\n\
  1005. -s    list of names to extract is sorted to match the archive\n\
  1006. -t    list a table of contents of an archive\n\
  1007. -T F    get names to extract or create from file F\n\
  1008. -v    verbosely list what files we process\n\
  1009. -x    extract files from an archive\n\
  1010. -z or Z    run the archive through compress(1)\n\
  1011. ", stderr);
  1012. }
  1013.  
  1014.  
  1015. /*
  1016.  * Set up to gather file names for tar.
  1017.  *
  1018.  * They can either come from stdin or from argv.
  1019.  */
  1020. name_init(argc, argv)
  1021.     int    argc;
  1022.     char    **argv;
  1023. {
  1024.  
  1025.     if (f_namefile) {
  1026.         if (optind < argc) {
  1027.             fprintf(stderr, "tar: too many args with -T option\n");
  1028.             exit(EX_ARGSBAD);
  1029.         }
  1030.         if (!strcmp(name_file, "-")) {
  1031.             namef = stdin;
  1032.         } else {
  1033.             namef = fopen(name_file, "r");
  1034.             if (namef == NULL) {
  1035.                 fprintf(stderr, "tar: ");
  1036.                 perror(name_file);
  1037.                 exit(EX_BADFILE);
  1038.             }
  1039.         }
  1040.     } else {
  1041.         /* Get file names from argv, after options. */
  1042.         n_argc = argc;
  1043.         n_argv = argv;
  1044.     }
  1045. }
  1046.  
  1047. /*
  1048.  * Get the next name from argv or the name file.
  1049.  *
  1050.  * Result is in static storage and can't be relied upon across two calls.
  1051.  */
  1052. char *
  1053. name_next()
  1054. {
  1055.     static char    buffer[NAMSIZ+2];    /* Holding pattern */
  1056.     register char    *p;
  1057.     register char    *q;
  1058.  
  1059.     if (namef == NULL) {
  1060.         /* Names come from argv, after options */
  1061.         if (optind < n_argc)
  1062.             return n_argv[optind++];
  1063.         return (char *)NULL;
  1064.     }
  1065.     p = fgets(buffer, NAMSIZ+1 /*nl*/, namef);
  1066.     if (p == NULL) return p;    /* End of file */
  1067.     q = p+strlen(p)-1;        /* Find the newline */
  1068.     *q-- = '\0';            /* Zap the newline */
  1069.     while (*q == '/')  *q-- = '\0';    /* Zap trailing slashes too */
  1070.     return p;
  1071. }
  1072.  
  1073.  
  1074. /*
  1075.  * Close the name file, if any.
  1076.  */
  1077. name_close()
  1078. {
  1079.  
  1080.     if (namef != NULL && namef != stdin) fclose(namef);
  1081. }
  1082.  
  1083.  
  1084. /*
  1085.  * Gather names in a list for scanning.
  1086.  * Could hash them later if we really care.
  1087.  *
  1088.  * If the names are already sorted to match the archive, we just
  1089.  * read them one by one.  name_gather reads the first one, and it
  1090.  * is called by name_match as appropriate to read the next ones.
  1091.  * At EOF, the last name read is just left in the buffer.
  1092.  * This option lets users of small machines extract an arbitrary
  1093.  * number of files by doing "tar t" and editing down the list of files.
  1094.  */
  1095. name_gather()
  1096. {
  1097.     register char *p;
  1098.     static struct name namebuf[1];    /* One-name buffer */
  1099.  
  1100.     if (f_sorted_names) {
  1101.         p = name_next();
  1102.         if (p) {
  1103.             namebuf->length = strlen(p);
  1104.             if (namebuf->length >= sizeof namebuf->name) {
  1105.                 fprintf(stderr, "Argument name too long: %s\n",
  1106.                     p);
  1107.                 namebuf->length = (sizeof namebuf->name) - 1;
  1108.             }
  1109.             strncpy(namebuf->name, p, namebuf->length);
  1110.             namebuf->next = (struct name *)NULL;
  1111.             namebuf->found = 0;
  1112.             namelist = namebuf;
  1113.             namelast = namelist;
  1114.         }
  1115.         return;
  1116.     }
  1117.  
  1118.     /* Non sorted names -- read them all in */
  1119.     while (NULL != (p = name_next())) {
  1120.         addname(p);
  1121.     }
  1122. }
  1123.  
  1124. /*
  1125.  * A name from the namelist has been found.
  1126.  * If it's just a list, 
  1127.  
  1128. /*
  1129.  * Add a name to the namelist.
  1130.  */
  1131. addname(name)
  1132.     char    *name;            /* pointer to name */
  1133. {
  1134.     register int    i;        /* Length of string */
  1135.     register struct name    *p;    /* Current struct pointer */
  1136.  
  1137.     i = strlen(name);
  1138.     /*NOSTRICT*/
  1139.     p = (struct name *)
  1140.         malloc((unsigned)(i + sizeof(struct name) - NAMSIZ));
  1141.     p->next = (struct name *)NULL;
  1142.     p->length = i;
  1143.     p->found = 0;
  1144.     strncpy(p->name, name, i);
  1145.     p->name[i] = '\0';    /* Null term */
  1146.     if (namelast) namelast->next = p;
  1147.     namelast = p;
  1148.     if (!namelist) namelist = p;
  1149. }
  1150.  
  1151.  
  1152. /*
  1153.  * Match a name from an archive, p, with a name from the namelist.
  1154.  *
  1155.  * FIXME: Allow regular expressions in the name list.
  1156.  */
  1157. name_match(p)
  1158.     register char *p;
  1159. {
  1160.     register struct name    *nlp;
  1161.     register int        len;
  1162.  
  1163. again:
  1164.     if (0 == (nlp = namelist))    /* Empty namelist is easy */
  1165.         return 1;
  1166.     len = strlen(p);
  1167.     for (; nlp != 0; nlp = nlp->next) {
  1168.         if ( nlp->name[0] == p[0]    /* First chars match */
  1169.          && nlp->length <= len        /* Archive len >= specified */
  1170.          && (p[nlp->length] == '\0' || p[nlp->length] == '/')
  1171.                         /* Full match on file/dirname */
  1172.          && strncmp(p, nlp->name, nlp->length) == 0) /* Name compare */
  1173.         {
  1174.             nlp->found = 1;        /* Remember it matched */
  1175.             return 1;        /* We got a match */
  1176.         }
  1177.     }
  1178.     /*
  1179.      * Filename from archive not found in namelist.
  1180.      * If we have the whole namelist here, just return 0.
  1181.      * Otherwise, read the next name in and compare it.
  1182.      * If this was the last name, namelist->found will remain on.
  1183.      * If not, we loop to compare the newly read name.
  1184.      */
  1185.     if (f_sorted_names && namelist->found) {
  1186.         name_gather();        /* Read one more */
  1187.         if (!namelist->found) goto again;
  1188.     }
  1189.     return 0;
  1190. }
  1191.  
  1192.  
  1193. /*
  1194.  * Print the names of things in the namelist that were not matched.
  1195.  */
  1196. names_notfound()
  1197. {
  1198.     register struct name    *nlp;
  1199.     register char        *p;
  1200.  
  1201.     for (nlp = namelist; nlp != 0; nlp = nlp->next) {
  1202.         if (!nlp->found) {
  1203.             fprintf(stderr, "tar: %s not found in archive\n",
  1204.                 nlp->name);
  1205.         }
  1206.         /*
  1207.          * We could free() the list, but the process is about
  1208.          * to die anyway, so save some CPU time.  Amigas and
  1209.          * other similarly broken software will need to waste
  1210.          * the time, though.
  1211.          */
  1212. #ifndef unix
  1213.         if (!f_sorted_names)
  1214.             free(nlp);
  1215. #endif unix
  1216.     }
  1217.     namelist = (struct name *)NULL;
  1218.     namelast = (struct name *)NULL;
  1219.  
  1220.     if (f_sorted_names) {
  1221.         while (0 != (p = name_next()))
  1222.             fprintf(stderr, "tar: %s not found in archive\n", p);
  1223.     }
  1224. }
  1225. @@@ Fin de tar.c
  1226. echo create.c 1>&2
  1227. cat >create.c <<'@@@ Fin de create.c'
  1228. /*
  1229.  * Create a tar archive.
  1230.  *
  1231.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  1232.  *
  1233.  * @(#)create.c 1.19 9/9/86 Public Domain - gnu
  1234.  */
  1235. #include <sys/types.h>
  1236. #include <sys/stat.h>
  1237. #include <fcntl.h>
  1238. #include <stdio.h>
  1239. #include <pwd.h>
  1240. #include <grp.h>
  1241.  
  1242. #ifdef BSD42
  1243. #include <sys/dir.h>
  1244. #else
  1245. /*
  1246.  * FIXME: On other systems there is no standard place for the header file
  1247.  * for the portable directory access routines.  Change the #include line
  1248.  * below to bring it in from wherever it is.
  1249.  */
  1250. #include "ndir.h"
  1251. #endif
  1252.  
  1253. #ifdef USG
  1254. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  1255. #endif
  1256.  
  1257. /*
  1258.  * V7 doesn't have a #define for this.
  1259.  */
  1260. #ifndef O_RDONLY
  1261. #define    O_RDONLY    0
  1262. #endif
  1263.  
  1264. #include "tar.h"
  1265.  
  1266. /*
  1267.  * If there are no symbolic links, there is no lstat().  Use stat().
  1268.  */
  1269. #ifndef S_IFLNK
  1270. #define lstat stat
  1271. #endif
  1272.  
  1273. extern char    *malloc();
  1274. extern char    *strcpy();
  1275. extern char    *strncpy();
  1276. extern int    errno;
  1277.  
  1278. union record *start_header();
  1279. void finish_header();
  1280. void finduname();
  1281. void findgname();
  1282. char *name_next();
  1283. void to_oct();
  1284.  
  1285.  
  1286. void
  1287. create_archive()
  1288. {
  1289.     register char    *p;
  1290.  
  1291.     open_archive(0);        /* Open for writing */
  1292.  
  1293.     while (p = name_next()) {
  1294.         dump_file(p);
  1295.     }
  1296.  
  1297.     write_eot();
  1298.     close_archive();
  1299.     name_close();
  1300. }        
  1301.  
  1302. /*
  1303.  * Dump a single file.  If it's a directory, recurse.
  1304.  * Result is 1 for success, 0 for failure.
  1305.  */
  1306. int
  1307. dump_file(p)
  1308.     char    *p;            /* File name to dump */
  1309. {
  1310.     struct stat    statbuf[1];
  1311.     union record    *header;
  1312.     char type;
  1313.  
  1314.     /*
  1315.      * Use stat if following (rather than dumping) 4.2BSD's
  1316.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  1317.      * systems, is #define'd to stat anyway.
  1318.      */
  1319.     if (0 != f_follow_links? stat(p, statbuf): lstat(p, statbuf))
  1320.     {
  1321. badperror:
  1322.         perror(p);
  1323. badfile:
  1324.         errors++;
  1325.         return 0;
  1326.     }
  1327.  
  1328.     switch (statbuf->st_mode & S_IFMT) {
  1329.  
  1330.     case S_IFREG:            /* Regular file */
  1331.     {
  1332.         int    f;        /* File descriptor */
  1333.         int    bufsize, count;
  1334.         register long    sizeleft;
  1335.         register union record     *start;
  1336.  
  1337.         /*
  1338.          * Handle a regular file with multiple links.
  1339.          *
  1340.          * We maintain a list of all such files that we've written so
  1341.          * far.  Any time we see another, we check the list and
  1342.          * avoid dumping the data again if we've done it once already.
  1343.          */
  1344.         if (statbuf->st_nlink > 1) {
  1345.             register struct link    *lp;
  1346.  
  1347.             /* First quick and dirty.  Hashing, etc later FIXME */
  1348.             for (lp = linklist; lp; lp = lp->next) {
  1349.                 if (lp->ino == statbuf->st_ino &&
  1350.                     lp->dev == statbuf->st_dev) {
  1351.                     /* We found a link. */
  1352.                     statbuf->st_size = 0;
  1353.                     header = start_header(p, statbuf);
  1354.                     if (header == NULL) goto badfile;
  1355.                     strcpy(header->header.linkname,
  1356.                         lp->name);
  1357.                     header->header.linkflag = LF_LINK;
  1358.                     finish_header(header);
  1359.                     if (f_verbose)
  1360.                         annorec(stdout, (char *)NULL);
  1361.                         printf("%s link to %s\n",
  1362.                             p, lp->name);
  1363.             /* Maybe remove from list after all links found? */
  1364.         /* If so, have to compare names in case he dumps twice. */
  1365.             /* Later: I don't understand the above.  If she
  1366.              * dumps the file twice, it would be BAD to dump
  1367.              * it the second time as a link...  gnu 25Jul86
  1368.              */
  1369.                     /* FIXME */
  1370.                     goto donefile;
  1371.                 }
  1372.             }
  1373.  
  1374.             /* Not found.  Add it to the list. */
  1375.             lp = (struct link *) malloc( (unsigned)
  1376.                 (strlen(p) + sizeof(struct link) - NAMSIZ));
  1377.             lp->ino = statbuf->st_ino;
  1378.             lp->dev = statbuf->st_dev;
  1379.             strcpy(lp->name, p);
  1380.             lp->next = linklist;
  1381.             linklist = lp;
  1382.         }
  1383.  
  1384.         sizeleft = statbuf->st_size;
  1385.         /* Don't bother opening empty, world readable files. */
  1386.         if (sizeleft > 0 || 0444 != (0444 & statbuf->st_mode)) {
  1387.             f = open(p, O_RDONLY);
  1388.             if (f < 0) goto badperror;
  1389.         } else {
  1390.             f = -1;
  1391.         }
  1392.         header = start_header(p, statbuf);
  1393.         if (header == NULL) goto badfile;
  1394.         finish_header(header);
  1395.         while (sizeleft > 0) {
  1396.             start = findrec();
  1397.             bufsize = endofrecs()->charptr - start->charptr;
  1398.             if (sizeleft < bufsize)
  1399.                 bufsize = sizeleft;
  1400.             count = read(f, start->charptr, bufsize);
  1401.             if (count < 0) {
  1402.                 annorec(stderr, tar);
  1403.                 fprintf(stderr,
  1404.                   "read error at byte %ld, reading %d bytes, in file ",
  1405.                     statbuf->st_size - sizeleft,
  1406.                     bufsize);
  1407.                 perror(p);    /* FIXME */
  1408.                 goto padit;
  1409.             }
  1410.             sizeleft -= count;
  1411.             userec(start+(count-1)/RECORDSIZE);
  1412.             if (count == bufsize) continue;
  1413.             annorec(stderr, tar);
  1414.             fprintf(stderr,
  1415.     "%s: file shrunk by %d bytes, padding with zeros.\n",
  1416.                 p, sizeleft);
  1417.             goto padit;        /* Short read */
  1418.         }
  1419.         if (f >= 0)
  1420.             (void)close(f);
  1421.  
  1422.         /* Clear last block garbage to zeros, FIXME */
  1423.  
  1424.         if (f_verbose) {
  1425.             annorec(stdout, (char *)NULL);
  1426.             printf("%s\n", p);
  1427.         }
  1428.     donefile:
  1429.         break;
  1430.  
  1431.         /*
  1432.          * File shrunk or gave error, pad out tape to match
  1433.          * the size we specified in the header.
  1434.          */
  1435.     padit:
  1436.         abort();
  1437.     }
  1438.  
  1439. #ifdef S_IFLNK
  1440.     case S_IFLNK:            /* Symbolic link */
  1441.     {
  1442.         int size;
  1443.  
  1444.         statbuf->st_size = 0;        /* Force 0 size on symlink */
  1445.         header = start_header(p, statbuf);
  1446.         if (header == NULL) goto badfile;
  1447.         size = readlink(p, header->header.linkname, NAMSIZ);
  1448.         if (size < 0) goto badperror;
  1449.         if (size == NAMSIZ) {
  1450.             annorec(stderr, tar);
  1451.             fprintf(stderr,
  1452.                 "%s: symbolic link too long\n", p);
  1453.             break;
  1454.         }
  1455.         header->header.linkname[size] = '\0';
  1456.         header->header.linkflag = LF_SYMLINK;
  1457.         finish_header(header);        /* Nothing more to do to it */
  1458.         if (f_verbose) {
  1459.             annorec(stdout, (char *)NULL);
  1460.             printf("%s\n", p);
  1461.         }
  1462.     }
  1463.         break;
  1464. #endif
  1465.  
  1466.     case S_IFDIR:            /* Directory */
  1467.     {
  1468.         register DIR *dirp;
  1469.         register struct direct *d;
  1470.         char namebuf[NAMSIZ+2];
  1471.         register int len;
  1472.  
  1473.         /* Build new prototype name */
  1474.         strncpy(namebuf, p, sizeof (namebuf));
  1475.         len = strlen(namebuf);
  1476.         while (len >= 1 && '/' == namebuf[len-1]) 
  1477.             len--;            /* Delete trailing slashes */
  1478.         namebuf[len++] = '/';        /* Now add exactly one back */
  1479.  
  1480.         /*
  1481.          * Output directory header record with permissions
  1482.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  1483.          * If Unix Std format, don't put / on end of dir name
  1484.          * If old archive format, don't write record at all.
  1485.          */
  1486.         if (!f_oldarch) {
  1487.             statbuf->st_size = 0;    /* Force 0 size on dir */
  1488.             /*
  1489.              * If people could really read standard archives,
  1490.              * this should be:        (FIXME)
  1491.             header = start_header(f_standard? p: namebuf, statbuf);
  1492.              * but since they'd interpret LF_DIR records as
  1493.              * regular files, we'd better put the / on the name.
  1494.              */
  1495.             header = start_header(namebuf, statbuf);
  1496.             if (header == NULL)
  1497.                 goto badfile;    /* eg name too long */
  1498.             if (f_standard) {
  1499.                 header->header.linkflag = LF_DIR;
  1500.             }
  1501.             finish_header(header);    /* Done with directory header */
  1502.         }
  1503.         if (f_verbose) {
  1504.             annorec(stdout, (char *)NULL);
  1505.             printf("%s\n", p);
  1506.         }
  1507.  
  1508.         /* Hack to remove "./" from the front of all the file names */
  1509.         if (len == 2 && namebuf[0] == '.') {
  1510.             len = 0;
  1511.         }
  1512.  
  1513.         /* Now output all the files in the directory */
  1514.         errno = 0;
  1515.         dirp = opendir(p);
  1516.         if (!dirp) {
  1517.             if (errno) {
  1518.                 perror (p);
  1519.             } else {
  1520.                 annorec(stderr, tar);
  1521.                 fprintf(stderr, "%s: error opening directory",
  1522.                     p);
  1523.             }
  1524.             break;
  1525.         }
  1526.         
  1527.         /* Should speed this up by cd-ing into the dir, FIXME */
  1528.         while (NULL != (d=readdir(dirp))) {
  1529.             /* Skip . and .. */
  1530.             if (d->d_name[0] == '.') {
  1531.                 if (d->d_name[1] == '\0') continue;
  1532.                 if (d->d_name[1] == '.') {
  1533.                     if (d->d_name[2] == '\0') continue;
  1534.                 }
  1535.             }
  1536.             if (d->d_namlen + len >= NAMSIZ) {
  1537.                 annorec(stderr, tar);
  1538.                 fprintf(stderr, "%s%s: name too long\n", 
  1539.                     namebuf, d->d_name);
  1540.                 continue;
  1541.             }
  1542.             strcpy(namebuf+len, d->d_name);
  1543.             dump_file(namebuf);
  1544.         }
  1545.  
  1546.         closedir(dirp);
  1547.     }
  1548.         break;
  1549.  
  1550.     case S_IFCHR:            /* Character special file */
  1551.         type = LF_CHR;
  1552.         goto easy;
  1553.  
  1554.     case S_IFBLK:            /* Block     special file */
  1555.         type = LF_BLK;
  1556.         goto easy;
  1557.  
  1558. #ifdef S_IFIFO
  1559.     case S_IFIFO:            /* Fifo      special file */
  1560.         type = LF_FIFO;
  1561. #endif S_IFIFO
  1562.  
  1563.     easy:
  1564.         if (!f_standard) goto unknown;
  1565.  
  1566.         statbuf->st_size = 0;        /* Force 0 size */
  1567.         header = start_header(p, statbuf);
  1568.         if (header == NULL) goto badfile;    /* eg name too long */
  1569.  
  1570.         header->header.linkflag = type;
  1571.         if (type != LF_FIFO) {
  1572.             to_oct((long) major(statbuf->st_rdev), 8,
  1573.                 header->header.devmajor);
  1574.             to_oct((long) minor(statbuf->st_rdev), 8,
  1575.                 header->header.devminor);
  1576.         }
  1577.  
  1578.         finish_header(header);
  1579.         if (f_verbose) {
  1580.             annorec(stdout, (char *)NULL);
  1581.             printf("%s\n", p);
  1582.         }
  1583.         break;
  1584.  
  1585.     default:
  1586.     unknown:
  1587.         annorec(stderr, tar);
  1588.         fprintf(stderr,
  1589.             "%s: Unknown file type; file ignored.\n", p);
  1590.         break;
  1591.     }
  1592.  
  1593.     return 1;            /* Success */
  1594. }
  1595.  
  1596.  
  1597. /*
  1598.  * Make a header block for the file  name  whose stat info is  st .
  1599.  * Return header pointer for success, NULL if the name is too long.
  1600.  */
  1601. union record *
  1602. start_header(name, st)
  1603.     char    *name;
  1604.     register struct stat *st;
  1605. {
  1606.     register union record *header;
  1607.  
  1608.     header = (union record *) findrec();
  1609.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1610.     strcpy(header->header.name, name);
  1611.     if (header->header.name[NAMSIZ-1]) {
  1612.         annorec(stderr, tar);
  1613.         fprintf(stderr, "%s: name too long\n", name);
  1614.         return NULL;
  1615.     }
  1616.     to_oct((long) (st->st_mode & ~S_IFMT),
  1617.                     8,  header->header.mode);
  1618.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1619.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1620.     to_oct((long) st->st_size,    1+12, header->header.size);
  1621.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1622.     /* header->header.linkflag is left as null */
  1623.  
  1624. #ifndef NONAMES
  1625.     /* Fill in new Unix Standard fields if desired. */
  1626.     if (f_standard) {
  1627.         header->header.linkflag = LF_NORMAL;    /* New default */
  1628.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1629.         finduname(header->header.uname, st->st_uid);
  1630.         findgname(header->header.gname, st->st_gid);
  1631.     }
  1632. #endif
  1633.     return header;
  1634. }
  1635.  
  1636. /* 
  1637.  * Finish off a filled-in header block and write it out.
  1638.  */
  1639. void
  1640. finish_header(header)
  1641.     register union record *header;
  1642. {
  1643.     register int    i, sum;
  1644.     register char    *p;
  1645.  
  1646.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1647.  
  1648.     sum = 0;
  1649.     p = header->charptr;
  1650.     for (i = sizeof(*header); --i >= 0; ) {
  1651.         /*
  1652.          * We can't use unsigned char here because of old compilers,
  1653.          * e.g. V7.
  1654.          */
  1655.         sum += 0xFF & *p++;
  1656.     }
  1657.  
  1658.     /*
  1659.      * Fill in the checksum field.  It's formatted differently
  1660.      * from the other fields:  it has [6] digits, a null, then a
  1661.      * space -- rather than digits, a space, then a null.
  1662.      * We use to_oct then write the null in over to_oct's space.
  1663.      * The final space is already there, from checksumming, and
  1664.      * to_oct doesn't modify it.
  1665.      *
  1666.      * This is a fast way to do:
  1667.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1668.      */
  1669.     to_oct((long) sum,    8,  header->header.chksum);
  1670.     header->header.chksum[6] = '\0';    /* Zap the space */
  1671.  
  1672.     userec(header);
  1673.     return;
  1674. }
  1675.  
  1676.  
  1677. /*
  1678.  * Quick and dirty octal conversion.
  1679.  * Converts long "value" into a "digs"-digit field at "where",
  1680.  * including a trailing space and room for a null.  "digs"==3 means
  1681.  * 1 digit, a space, and room for a null.
  1682.  *
  1683.  * We assume the trailing null is already there and don't fill it in.
  1684.  * This fact is used by start_header and finish_header, so don't change it!
  1685.  *
  1686.  * This should be equivalent to:
  1687.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1688.  * except that sprintf fills in the trailing null and we don't.
  1689.  */
  1690. void
  1691. to_oct(value, digs, where)
  1692.     register long    value;
  1693.     register int    digs;
  1694.     register char    *where;
  1695. {
  1696.     
  1697.     --digs;                /* Trailing null slot is left alone */
  1698.     where[--digs] = ' ';        /* Put in the space, though */
  1699.  
  1700.     /* Produce the digits -- at least one */
  1701.     do {
  1702.         where[--digs] = '0' + (value & 7);    /* one octal digit */
  1703.         value >>= 3;
  1704.     } while (digs > 0 && value != 0);
  1705.  
  1706.     /* Leading spaces, if necessary */
  1707.     while (digs > 0)
  1708.         where[--digs] = ' ';
  1709.  
  1710. }
  1711.  
  1712.  
  1713. /*
  1714.  * Write the EOT block(s).
  1715.  */
  1716. write_eot()
  1717. {
  1718.     union record *p;
  1719.  
  1720.     p = findrec();
  1721.     bzero(p->charptr, RECORDSIZE);
  1722.     userec(p);
  1723.     /* FIXME, only one EOT block should be needed. */
  1724.     p = findrec();
  1725.     bzero(p->charptr, RECORDSIZE);
  1726.     userec(p);
  1727. }
  1728. @@@ Fin de create.c
  1729. echo extract.c 1>&2
  1730. cat >extract.c <<'@@@ Fin de extract.c'
  1731. /*
  1732.  * Extract files from a tar archive.
  1733.  *
  1734.  * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  1735.  *
  1736.  * @(#) extract.c 1.17 86/10/29 Public Domain - gnu
  1737.  */
  1738.  
  1739. #include <stdio.h>
  1740. #include <errno.h>
  1741. #include <sys/types.h>
  1742. #include <sys/stat.h>
  1743.  
  1744. #ifdef BSD42
  1745. #include <sys/file.h>
  1746. #endif
  1747.  
  1748. #ifdef USG
  1749. #include <fcntl.h>
  1750. #endif
  1751.  
  1752. extern int errno;            /* From libc.a */
  1753. extern char *index();            /* From libc.a or port.c */
  1754.  
  1755. #include "tar.h"
  1756.  
  1757. extern union record *head;        /* Points to current tape header */
  1758. extern struct stat hstat[1];        /* Stat struct corresponding */
  1759.  
  1760. extern void print_header();
  1761. extern void skip_file();
  1762. extern void pr_mkdir();
  1763.  
  1764. int make_dirs();            /* Makes required directories */
  1765.  
  1766. time_t now = 0;                /* Current time */
  1767.  
  1768. /*
  1769.  * Extract a file from the archive.
  1770.  */
  1771. void
  1772. extract_archive()
  1773. {
  1774.     register char *data;
  1775.     int fd, check, namelen, written;
  1776.     long size;
  1777.     time_t acc_upd_times[2];
  1778.     int    standard;        /* Is header standard? */
  1779.  
  1780.     saverec(&head);            /* Make sure it sticks around */
  1781.     userec(head);            /* And go past it in the archive */
  1782.     decode_header(head, hstat, &standard, 1);    /* Snarf fields */
  1783.  
  1784.     /* Print the record from 'head' and 'hstat' */
  1785.     if (f_verbose)
  1786.         print_header();
  1787.  
  1788.     switch (head->header.linkflag) {
  1789.  
  1790.     default:
  1791.         annofile(stderr, tar);
  1792.         fprintf(stderr, "Unknown file type %d for %s\n",
  1793.             head->header.linkflag, head->header.name);
  1794.         /* FALL THRU */
  1795.  
  1796.     case LF_OLDNORMAL:
  1797.     case LF_NORMAL:
  1798.         /*
  1799.          * Appears to be a file.
  1800.          * See if it's really a directory.
  1801.          */
  1802.         namelen = strlen(head->header.name)-1;
  1803.         if (head->header.name[namelen] == '/')
  1804.             goto really_dir;
  1805.  
  1806.         /* FIXME, deal with protection issues */
  1807.         /* FIXME, f_keep doesn't work on V7, st_mode loses too */
  1808.     again_file:
  1809.         fd = open(head->header.name,
  1810.             f_keep?
  1811.             O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_EXCL:
  1812.             O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
  1813.             hstat->st_mode);
  1814.         if (fd < 0) {
  1815.             if (make_dirs(head->header.name))
  1816.                 goto again_file;
  1817.             annofile(stderr, tar);
  1818.             fprintf(stderr, "Could not make file ");
  1819.             perror(head->header.name);
  1820.             skip_file((long)hstat->st_size);
  1821.             goto quit;
  1822.         }
  1823.  
  1824.         for (size = hstat->st_size;
  1825.              size > 0;
  1826.              size -= written) {
  1827.             /*
  1828.              * Locate data, determine max length
  1829.              * writeable, write it, record that
  1830.              * we have used the data, then check
  1831.              * if the write worked.
  1832.              */
  1833.             data = findrec()->charptr;
  1834.             written = endofrecs()->charptr - data;
  1835.             if (written > size) written = size;
  1836.             errno = 0;
  1837.             check = write (fd, data, written);
  1838.             /*
  1839.              * The following is in violation of strict
  1840.              * typing, since the arg to userec
  1841.              * should be a struct rec *.  FIXME.
  1842.              */
  1843.             userec(data + written - 1);
  1844.             if (check == written) continue;
  1845.             /*
  1846.              * Error in writing to file.
  1847.              * Print it, skip to next file in archive.
  1848.              */
  1849.             annofile(stderr, tar);
  1850.             fprintf(stderr,
  1851.     "Tried to write %d bytes to file, could only write %d:\n",
  1852.                 written, check);
  1853.             perror(head->header.name);
  1854.             (void) close(fd);
  1855.             skip_file((long)(size - written));
  1856.             goto quit;
  1857.         }
  1858.  
  1859.         check = close(fd);
  1860.         if (check < 0) {
  1861.             annofile(stderr, tar);
  1862.             fprintf(stderr, "Error while closing ");
  1863.             perror(head->header.name);
  1864.         }
  1865.         
  1866.         /* FIXME, deal with uid/gid/mtimes/suid */
  1867.  
  1868.         /*
  1869.          * Set the modified time of the file.
  1870.          * 
  1871.          * Note that we set the accessed time to "now", which
  1872.          * is really "the time we started extracting files".
  1873.          */
  1874.         if (!f_modified) {
  1875.             if (!now)
  1876.                 now = time((time_t *)0); /* Just do it once */
  1877.             acc_upd_times[0] = now;             /* Accessed now */
  1878.             acc_upd_times[1] = hstat->st_mtime; /* Mod'd */
  1879.             if (utime(head->header.name, acc_upd_times) < 0) {
  1880.                 annofile(stderr, tar);
  1881.                 perror(head->header.name);
  1882.             }
  1883.         }
  1884.  
  1885.         /*
  1886.          * If '-p' is not set, OR if the file has pretty normal
  1887.          * mode bits, we can skip the chmod and save a sys call.
  1888.          * This works because we did umask(0) if -p is set, so
  1889.          * the open() that created the file will have set the modes
  1890.          * properly.  
  1891.          * FIXME: I don't know what open() does w/UID/GID/SVTX bits.
  1892.          * However, if we've done a chown(), they got reset.
  1893.          */
  1894.         if (f_use_protection
  1895.             && (hstat->st_mode & (S_ISUID|S_ISGID|S_ISVTX))) {
  1896.             if (chmod(head->header.name, (int)hstat->st_mode) < 0) {
  1897.                 annofile(stderr, tar);
  1898.                 perror(head->header.name);
  1899.             }
  1900.         }
  1901.  
  1902.     quit:
  1903.         break;
  1904.  
  1905.     case LF_LINK:
  1906.     again_link:
  1907.         check = link (head->header.linkname,
  1908.                   head->header.name);
  1909.         /* FIXME, don't worry uid, gid, etc... */
  1910.         if (check == 0)
  1911.             break;
  1912.         if (make_dirs(head->header.linkname))
  1913.             goto again_link;
  1914.         annofile(stderr, tar);
  1915.         fprintf(stderr, "Could not link %s to ",
  1916.             head->header.name);
  1917.         perror(head->header.linkname);
  1918.         break;
  1919.  
  1920. #ifdef S_IFLNK
  1921.     case LF_SYMLINK:
  1922.     again_symlink:
  1923.         check = symlink(head->header.linkname,
  1924.                     head->header.name);
  1925.         /* FIXME, don't worry uid, gid, etc... */
  1926.         if (check == 0)
  1927.             break;
  1928.         if (make_dirs(head->header.linkname))
  1929.             goto again_symlink;
  1930.         annofile(stderr, tar);
  1931.         fprintf(stderr, "Could not create symlink ");
  1932.         perror(head->header.linkname);
  1933.         break;
  1934. #endif
  1935.  
  1936.     case LF_CHR:
  1937.         hstat->st_mode |= S_IFCHR;
  1938.         goto make_node;
  1939.  
  1940.     case LF_BLK:
  1941.         hstat->st_mode |= S_IFBLK;
  1942.     make_node:
  1943.         check = mknod(head->header.name, (int) hstat->st_mode,
  1944.             (int) hstat->st_dev);
  1945.         if (check != 0) {
  1946.             if (make_dirs(head->header.name))
  1947.                 goto make_node;
  1948.             annofile(stderr, tar);
  1949.             fprintf(stderr, "Could not make special file ");
  1950.             perror(head->header.name);
  1951.             break;
  1952.         };
  1953.         break;
  1954.  
  1955.     case LF_DIR:
  1956.         /* Check for trailing / */
  1957.         namelen = strlen(head->header.name)-1;
  1958.     really_dir:
  1959.         while (namelen && head->header.name[namelen] == '/')
  1960.             head->header.name[namelen--] = '\0';    /* Zap / */
  1961.         
  1962.         /* FIXME, deal with umask */
  1963.     again_dir:
  1964.         check = mkdir(head->header.name, (int)hstat->st_mode);
  1965.         if (check != 0) {
  1966.             if (make_dirs(head->header.name))
  1967.                 goto again_dir;
  1968.             annofile(stderr, tar);
  1969.             fprintf(stderr, "Could not make directory ");
  1970.             perror(head->header.name);
  1971.             break;
  1972.         }
  1973.         
  1974.         /* FIXME, deal with uid/gid */
  1975.         /* FIXME, Remember timestamps for after files created? */
  1976.         break;
  1977.  
  1978.     case LF_FIFO:
  1979.         abort();    /* FIXME */
  1980.         break;
  1981.  
  1982.     }
  1983.  
  1984.     /* We don't need to save it any longer. */
  1985.     saverec((union record **) 0);    /* Unsave it */
  1986. }
  1987.  
  1988. /*
  1989.  * After a file/link/symlink/dir creation has failed, see if
  1990.  * it's because some required directory was not present, and if
  1991.  * so, create all required dirs.
  1992.  */
  1993. int
  1994. make_dirs(pathname)
  1995.     char *pathname;
  1996. {
  1997.     char *p;            /* Points into path */
  1998.     int madeone = 0;        /* Did we do anything yet? */
  1999.     int save_errno = errno;        /* Remember caller's errno */
  2000.     int check;
  2001.  
  2002.     if (errno != ENOENT)
  2003.         return 0;        /* Not our problem */
  2004.  
  2005.     for (p = index(pathname, '/'); p != NULL; p = index(p+1, '/')) {
  2006.         /* Avoid mkdir of empty string, if leading or double '/' */
  2007.         if (p == pathname || p[-1] == '/')
  2008.             continue;
  2009.         /* Avoid mkdir where last part of path is '.' */
  2010.         if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  2011.             continue;
  2012.         *p = 0;                /* Truncate the path there */
  2013.         check = mkdir (pathname, 0777);    /* Try to create it as a dir */
  2014.         *p = '/';
  2015.         if (check == 0) {
  2016.             /* FIXME chown, chgrp it same as file being created */
  2017.             /* FIXME, show mode as modified by current umask */
  2018.             pr_mkdir(pathname, p-pathname, 0777);
  2019.             madeone++;        /* Remember if we made one */
  2020.             continue;
  2021.         }
  2022.         if (errno == EEXIST)        /* Directory already exists */
  2023.             continue;
  2024.         /*
  2025.          * Some other error in the mkdir.  We return to the caller.
  2026.          */
  2027.         break;
  2028.     }
  2029.  
  2030.     errno = save_errno;        /* Restore caller's errno */
  2031.     return madeone;            /* Tell them to retry if we made one */
  2032. }
  2033. @@@ Fin de extract.c
  2034. echo buffer.c 1>&2
  2035. cat >buffer.c <<'@@@ Fin de buffer.c'
  2036. /*
  2037.  * Buffer management for public domain tar.
  2038.  *
  2039.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  2040.  *
  2041.  * @(#) buffer.c 1.14 10/28/86 Public Domain - gnu
  2042.  */
  2043.  
  2044. #include <stdio.h>
  2045. #include <errno.h>
  2046. #include <sys/types.h>        /* For non-Berkeley systems */
  2047. #include <sys/file.h>
  2048. #include <signal.h>
  2049.  
  2050. #include "tar.h"
  2051. #include "port.h"
  2052.  
  2053. #define    STDIN    0        /* Standard input  file descriptor */
  2054. #define    STDOUT    1        /* Standard output file descriptor */
  2055.  
  2056. #define    PREAD    0        /* Read  file descriptor from pipe() */
  2057. #define    PWRITE    1        /* Write file descriptor from pipe() */
  2058.  
  2059. extern char    *valloc();
  2060.  
  2061. /*
  2062.  * V7 doesn't have a #define for this.
  2063.  */
  2064. #ifndef O_RDONLY
  2065. #define    O_RDONLY    0
  2066. #endif
  2067.  
  2068. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  2069.                    it can't exec compress.  We hope compress
  2070.                    never returns this status! */
  2071. /*
  2072.  * The record pointed to by save_rec should not be overlaid
  2073.  * when reading in a new tape block.  Copy it to record_save_area first, and
  2074.  * change the pointer in *save_rec to point to record_save_area.
  2075.  * Saved_recno records the record number at the time of the save.
  2076.  * This is used by annofile() to print the record number of a file's
  2077.  * header record.
  2078.  */
  2079. static union record **save_rec;
  2080. static union record record_save_area;
  2081. static int        saved_recno;
  2082.  
  2083. /*
  2084.  * PID of child compress program, if f_compress.
  2085.  */
  2086. static int    compress_pid;
  2087.  
  2088. /*
  2089.  * Record number of the start of this block of records
  2090.  */
  2091. static int    baserec;
  2092.  
  2093. /*
  2094.  * Error recovery stuff
  2095.  */
  2096. static int    r_error_count;
  2097.  
  2098.  
  2099. /*
  2100.  * Return the location of the next available input or output record.
  2101.  */
  2102. union record *
  2103. findrec()
  2104. {
  2105.     if (ar_record == ar_last) {
  2106.         flush_archive();
  2107.         if (ar_record == ar_last)
  2108.             return (union record *)NULL;    /* EOF */
  2109.     }
  2110.     return ar_record;
  2111. }
  2112.  
  2113.  
  2114. /*
  2115.  * Indicate that we have used all records up thru the argument.
  2116.  * (should the arg have an off-by-1? XXX FIXME)
  2117.  */
  2118. void
  2119. userec(rec)
  2120.     union record *rec;
  2121. {
  2122.     while(rec >= ar_record)
  2123.         ar_record++;
  2124.     /*
  2125.      * Do NOT flush the archive here.  If we do, the same
  2126.      * argument to userec() could mean the next record (if the
  2127.      * input block is exactly one record long), which is not what
  2128.      * is intended.
  2129.      */
  2130.     if (ar_record > ar_last)
  2131.         abort();
  2132. }
  2133.  
  2134.  
  2135. /*
  2136.  * Return a pointer to the end of the current records buffer.
  2137.  * All the space between findrec() and endofrecs() is available
  2138.  * for filling with data, or taking data from.
  2139.  */
  2140. union record *
  2141. endofrecs()
  2142. {
  2143.     return ar_last;
  2144. }
  2145.  
  2146.  
  2147. /*
  2148.  * Open an archive file.  The argument specifies whether we are
  2149.  * reading or writing.
  2150.  */
  2151. open_archive(read)
  2152.     int read;
  2153. {
  2154.  
  2155.     if (ar_file[0] == '-' && ar_file[1] == '\0') {
  2156.         if (read)    archive = STDIN;
  2157.         else        archive = STDOUT;
  2158.     } else if (read) {
  2159.         archive = open(ar_file, O_RDONLY);
  2160.     } else {
  2161.         archive = creat(ar_file, 0666);
  2162.     }
  2163.  
  2164.     if (archive < 0) {
  2165.         perror(ar_file);
  2166.         exit(EX_BADARCH);
  2167.     }
  2168.  
  2169.     /*NOSTRICT*/
  2170.     ar_block = (union record *) valloc((unsigned)blocksize);
  2171.     if (!ar_block) {
  2172.         fprintf(stderr,
  2173.         "tar: could not allocate memory for blocking factor %d\n",
  2174.             blocking);
  2175.         exit(EX_ARGSBAD);
  2176.     }
  2177.  
  2178.     ar_record = ar_block;
  2179.     ar_last   = ar_block + blocking;
  2180.  
  2181.     /*
  2182.      * Handle compressed archives.
  2183.      *
  2184.      * FIXME, currently supported for reading only.
  2185.      * FIXME, writing involves forking again for a small process
  2186.      * that will reblock the output of compress to the user's specs.
  2187.      */
  2188.     if (f_compress) {
  2189.         int pipes[2];
  2190.         int err;
  2191.  
  2192.         if (!read) {
  2193.             fprintf(stderr,
  2194.                 "tar: cannot write compressed archives yet.\n");
  2195.             exit(EX_ARGSBAD);
  2196.         }
  2197.  
  2198.         /* Create a pipe to get compress's output to us */
  2199.         err = pipe(pipes);
  2200.         if (err < 0) {
  2201.             perror ("tar: cannot create pipe to compress");
  2202.             exit(EX_SYSTEM);
  2203.         }
  2204.         
  2205.         /* Fork compress process */
  2206.         compress_pid = fork();
  2207.         if (compress_pid < 0) {
  2208.             perror("tar: cannot fork compress");
  2209.             exit(EX_SYSTEM);
  2210.         }
  2211.  
  2212.         /*
  2213.          * Child process.
  2214.          * 
  2215.           * Move input to stdin, write side of pipe to stdout,
  2216.          * then exec compress.
  2217.          */
  2218.         if (compress_pid == 0) {
  2219.             (void) close (pipes[PREAD]);    /* We won't use it */
  2220.             if (archive != STDIN) {
  2221.                 (void) close(STDIN);
  2222.                 err = dup(archive);
  2223.                 if (err != 0) {
  2224.                     perror(
  2225.                      "tar: cannot dup input to stdin");
  2226.                     exit(EX_SYSTEM);
  2227.                 }
  2228.                 (void) close(archive);
  2229.             }
  2230.             if (pipes[PWRITE] != STDOUT) {
  2231.                 (void) close (STDOUT);
  2232.                 err = dup (pipes[PWRITE]);
  2233.                 if (err != STDOUT) {
  2234.                     perror(
  2235.                       "tar: cannot dup pipe output");
  2236.                     exit(MAGIC_STAT);
  2237.                 }
  2238.                 (void) close (pipes[PWRITE]);
  2239.             }
  2240.             execlp("compress", "compress", "-d", (char *)0);
  2241.             perror("tar: cannot exec compress");
  2242.             exit(MAGIC_STAT);
  2243.         }
  2244.  
  2245.         /*
  2246.          * Parent process.  Clean up.
  2247.          * FIXME, note that this may leave standard input closed,
  2248.          * if the compressed archive was on standard input.
  2249.          */
  2250.         (void) close (archive);        /* Close compressed archive */
  2251.         (void) close (pipes[PWRITE]);    /* Close write side of pipe */
  2252.         archive = pipes[PREAD];        /* Read side is our archive */
  2253.  
  2254. #ifdef BSD42
  2255.         f_reblock++;        /* Pipe will give random # of bytes */
  2256. #endif BSD42
  2257.     }
  2258.  
  2259.     ar_reading = read;
  2260.     if (read) {
  2261.         ar_last = ar_block;        /* Set up for 1st block = # 0 */
  2262.         flush_archive();
  2263.     }
  2264. }
  2265.  
  2266.  
  2267. /*
  2268.  * Remember a union record * as pointing to something that we
  2269.  * need to keep when reading onward in the file.  Only one such
  2270.  * thing can be remembered at once, and it only works when reading
  2271.  * an archive.
  2272.  */
  2273. saverec(pointer)
  2274.     union record **pointer;
  2275. {
  2276.  
  2277.     save_rec = pointer;
  2278.     saved_recno = baserec + ar_record - ar_block;
  2279. }
  2280.  
  2281. /*
  2282.  * Perform a write to flush the buffer.
  2283.  */
  2284. fl_write()
  2285. {
  2286.     int err;
  2287.  
  2288.     err = write(archive, ar_block->charptr, blocksize);
  2289.     if (err == blocksize) return;
  2290.     /* FIXME, multi volume support on write goes here */
  2291.     if (err < 0)
  2292.         perror(ar_file);
  2293.     else
  2294.         fprintf(stderr, "tar: %s: write failed, short %d bytes\n",
  2295.             ar_file, blocksize - err);
  2296.     exit(EX_BADARCH);
  2297. }
  2298.  
  2299.  
  2300. /*
  2301.  * Handle read errors on the archive.
  2302.  *
  2303.  * If the read should be retried, readerror() returns to the caller.
  2304.  */
  2305. void
  2306. readerror()
  2307. {
  2308. #    define    READ_ERROR_MAX    10
  2309.  
  2310.     read_error_flag++;        /* Tell callers */
  2311.  
  2312.     annorec(stderr, tar);
  2313.     fprintf(stderr, "Read error on ");
  2314.     perror(ar_file);
  2315.  
  2316.     if (baserec == 0) {
  2317.         /* First block of tape.  Probably stupidity error */
  2318.         exit(EX_BADARCH);
  2319.     }    
  2320.  
  2321.     /*
  2322.      * Read error in mid archive.  We retry up to READ_ERROR_MAX times
  2323.      * and then give up on reading the archive.  We set read_error_flag
  2324.      * for our callers, so they can cope if they want.
  2325.      */
  2326.     if (r_error_count++ > READ_ERROR_MAX) {
  2327.         annorec(stderr, tar);
  2328.         fprintf(stderr, "Too many errors, quitting.\n");
  2329.         exit(EX_BADARCH);
  2330.     }
  2331.     return;
  2332. }
  2333.  
  2334.  
  2335. /*
  2336.  * Perform a read to flush the buffer.
  2337.  */
  2338. fl_read()
  2339. {
  2340.     int err;        /* Result from system call */
  2341.     int left;        /* Bytes left */
  2342.     char *more;        /* Pointer to next byte to read */
  2343.  
  2344.     /*
  2345.      * Clear the count of errors.  This only applies to a single
  2346.      * call to fl_read.  We leave read_error_flag alone; it is
  2347.      * only turned off by higher level software.
  2348.      */
  2349.     r_error_count = 0;    /* Clear error count */
  2350.  
  2351.     /*
  2352.      * If we are about to wipe out a record that
  2353.      * somebody needs to keep, copy it out to a holding
  2354.      * area and adjust somebody's pointer to it.
  2355.      */
  2356.     if (save_rec &&
  2357.         *save_rec >= ar_record &&
  2358.         *save_rec < ar_last) {
  2359.         record_save_area = **save_rec;
  2360.         *save_rec = &record_save_area;
  2361.     }
  2362. error_loop:
  2363.     err = read(archive, ar_block->charptr, blocksize);
  2364.     if (err == blocksize) return;
  2365.     if (err < 0) {
  2366.         readerror();
  2367.         goto error_loop;    /* Try again */
  2368.     }
  2369.  
  2370.     more = ar_block->charptr + err;
  2371.     left = blocksize - err;
  2372.  
  2373. again:
  2374.     if (0 == (((unsigned)left) % RECORDSIZE)) {
  2375.         /* FIXME, for size=0, multi vol support */
  2376.         /* On the first block, warn about the problem */
  2377.         if (!f_reblock && baserec == 0 && f_verbose) {
  2378.             annorec(stderr, tar);
  2379.             fprintf(stderr, "Blocksize = %d records\n",
  2380.                 err / RECORDSIZE);
  2381.         }
  2382.         ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
  2383.         return;
  2384.     }
  2385.     if (f_reblock) {
  2386.         /*
  2387.          * User warned us about this.  Fix up.
  2388.          */
  2389.         if (left > 0) {
  2390. error_loop_2:
  2391.             err = read(archive, more, left);
  2392.             if (err < 0) {
  2393.                 readerror();
  2394.                 goto error_loop_2;    /* Try again */
  2395.             }
  2396.             if (err == 0) {
  2397.                 annorec(stderr, tar);
  2398.                 fprintf(stderr,
  2399.         "%s: eof not on block boundary, strange...\n",
  2400.                     ar_file);
  2401.                 exit(EX_BADARCH);
  2402.             }
  2403.             left -= err;
  2404.             more += err;
  2405.             goto again;
  2406.         }
  2407.     } else {
  2408.         annorec(stderr, tar);
  2409.         fprintf(stderr, "%s: read %d bytes, strange...\n",
  2410.             ar_file, err);
  2411.         exit(EX_BADARCH);
  2412.     }
  2413. }
  2414.  
  2415.  
  2416. /*
  2417.  * Flush the current buffer to/from the archive.
  2418.  */
  2419. flush_archive()
  2420. {
  2421.     baserec += ar_last - ar_block;/* Keep track of block #s */
  2422.     ar_record = ar_block;        /* Restore pointer to start */
  2423.     ar_last = ar_block + blocking;    /* Restore pointer to end */
  2424.  
  2425.     if (!ar_reading) 
  2426.         fl_write();
  2427.     else
  2428.         fl_read();
  2429. }
  2430.  
  2431. /*
  2432.  * Close the archive file.
  2433.  */
  2434. close_archive()
  2435. {
  2436.     int child;
  2437.     int status;
  2438.  
  2439.     if (!ar_reading) flush_archive();
  2440.     (void) close(archive);
  2441.  
  2442.     if (f_compress) {
  2443.         /*
  2444.          * Loop waiting for the right child to die, or for
  2445.          * no more kids.
  2446.          */
  2447.         while (((child = wait(&status)) != compress_pid) && child != -1)
  2448.             ;
  2449.  
  2450.         if (child != -1) {
  2451.             switch (TERM_SIGNAL(status)) {
  2452.             case 0:        /* Terminated by itself */
  2453.                 if (TERM_VALUE(status) == MAGIC_STAT) {
  2454.                     exit(EX_SYSTEM);/* Child had trouble */
  2455.                 }
  2456.                 if (TERM_VALUE(status))
  2457.                     fprintf(stderr,
  2458.                   "tar: compress child returned status %d\n",
  2459.                         TERM_VALUE(status));
  2460.             case SIGPIPE:
  2461.                 break;        /* This is OK. */
  2462.  
  2463.             default:
  2464.                 fprintf(stderr,
  2465.                  "tar: compress child died with signal %d%s\n",
  2466.                  TERM_SIGNAL(status),
  2467.                  TERM_COREDUMP(status)? " (core dumped)": "");
  2468.             }
  2469.         }
  2470.     }
  2471. }
  2472.  
  2473.  
  2474. /*
  2475.  * Message management.
  2476.  *
  2477.  * anno writes a message prefix on stream (eg stdout, stderr).
  2478.  *
  2479.  * The specified prefix is normally output followed by a colon and a space.
  2480.  * However, if other command line options are set, more output can come
  2481.  * out, such as the record # within the archive.
  2482.  *
  2483.  * If the specified prefix is NULL, no output is produced unless the
  2484.  * command line option(s) are set.
  2485.  *
  2486.  * If the third argument is 1, the "saved" record # is used; if 0, the
  2487.  * "current" record # is used.
  2488.  */
  2489. void
  2490. anno(stream, prefix, savedp)
  2491.     FILE    *stream;
  2492.     char    *prefix;
  2493.     int    savedp;
  2494. {
  2495. #    define    MAXANNO    50
  2496.     char    buffer[MAXANNO];    /* Holds annorecment */
  2497. #    define    ANNOWIDTH 13
  2498.     int    space;
  2499.  
  2500.     if (f_sayblock) {
  2501.         if (prefix) {
  2502.             fputs(prefix, stream);
  2503.             putc(' ', stream);
  2504.         }
  2505.         sprintf(buffer, "rec %d: ",
  2506.             savedp?    saved_recno:
  2507.                 baserec + ar_record - ar_block);
  2508.         fputs(buffer, stream);
  2509.         space = ANNOWIDTH - strlen(buffer);
  2510.         if (space > 0) {
  2511.             fprintf(stream, "%*s", space, "");
  2512.         }
  2513.     } else if (prefix) {
  2514.         fputs(prefix, stream);
  2515.         fputs(": ", stream);
  2516.     }
  2517. }
  2518. @@@ Fin de buffer.c
  2519. echo getoldopt.c 1>&2
  2520. cat >getoldopt.c <<'@@@ Fin de getoldopt.c'
  2521. /*
  2522.  * Plug-compatible replacement for getopt() for parsing tar-like
  2523.  * arguments.  If the first argument begins with "-", it uses getopt;
  2524.  * otherwise, it uses the old rules used by tar, dump, and ps.
  2525.  *
  2526.  * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
  2527.  * in the Pubic Domain for your edification and enjoyment.
  2528.  *
  2529.  * @(#)getoldopt.c 1.4 2/4/86 Public Domain - gnu
  2530.  */
  2531.  
  2532. #include <stdio.h>
  2533.  
  2534.  
  2535. int
  2536. getoldopt(argc, argv, optstring)
  2537.     int    argc;
  2538.     char    **argv;
  2539.     char    *optstring;
  2540. {
  2541.     extern char    *optarg;    /* Points to next arg */
  2542.     extern int    optind;        /* Global argv index */
  2543.     static char    *key;        /* Points to next keyletter */
  2544.     static char    use_getopt;    /* !=0 if argv[1][0] was '-' */
  2545.     extern char    *index();
  2546.     char        c;
  2547.     char        *place;
  2548.  
  2549.     optarg = NULL;
  2550.     
  2551.     if (key == NULL) {        /* First time */
  2552.         if (argc < 2) return EOF;
  2553.         key = argv[1];
  2554.         if (*key == '-')
  2555.             use_getopt++;
  2556.         else
  2557.             optind = 2;
  2558.     }
  2559.  
  2560.     if (use_getopt)
  2561.         return getopt(argc, argv, optstring);
  2562.  
  2563.     c = *key++;
  2564.     if (c == '\0') {
  2565.         key--;
  2566.         return EOF;
  2567.     }
  2568.     place = index(optstring, c);
  2569.  
  2570.     if (place == NULL || c == ':') {
  2571.         fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  2572.         return('?');
  2573.     }
  2574.  
  2575.     place++;
  2576.     if (*place == ':') {
  2577.         if (optind < argc) {
  2578.             optarg = argv[optind];
  2579.             optind++;
  2580.         } else {
  2581.             fprintf(stderr, "%s: %c argument missing\n",
  2582.                 argv[0], c);
  2583.             return('?');
  2584.         }
  2585.     }
  2586.  
  2587.     return(c);
  2588. }
  2589. @@@ Fin de getoldopt.c
  2590. echo list.c 1>&2
  2591. cat >list.c <<'@@@ Fin de list.c'
  2592. /*
  2593.  * List a tar archive.
  2594.  *
  2595.  * Also includes support routines for reading a tar archive.
  2596.  *
  2597.  * Pubic Domain version written 26 Aug 1985 by John Gilmore (ihnp4!hoptoad!gnu).
  2598.  *
  2599.  * @(#)list.c 1.18 9/23/86 Public Domain - gnu
  2600.  */
  2601. #include <stdio.h>
  2602. #include <ctype.h>
  2603. #include <sys/types.h>
  2604. #include <sys/stat.h>
  2605. #include <sys/file.h>
  2606.  
  2607. char *ctime();                /* From libc.a */
  2608.  
  2609. #define    isodigit(c)    ( ((c) >= '0') && ((c) <= '7') )
  2610.  
  2611. #include "tar.h"
  2612.  
  2613. long from_oct();            /* Decode octal number */
  2614. void demode();                /* Print file mode */
  2615.  
  2616. union record *head;            /* Points to current archive header */
  2617. struct stat hstat[1];            /* Stat struct corresponding */
  2618.  
  2619. void print_header();
  2620. void skip_file();
  2621.  
  2622.  
  2623. /*
  2624.  * Main loop for reading an archive.
  2625.  */
  2626. void
  2627. read_and(do_something)
  2628.     void (*do_something)();
  2629. {
  2630.     int status = 1;
  2631.     int prev_status;
  2632.  
  2633.     name_gather();            /* Gather all the names */
  2634.     open_archive(1);        /* Open for reading */
  2635.  
  2636.     for(;;) {
  2637.         prev_status = status;
  2638.         status = read_header();
  2639.         switch (status) {
  2640.  
  2641.         case 1:            /* Valid header */
  2642.             /* We should decode next field (mode) first... */
  2643.             /* Ensure incoming names are null terminated. */
  2644.             head->header.name[NAMSIZ-1] = '\0';
  2645.             
  2646.             if (!name_match(head->header.name)) {
  2647.                 /* Skip past it in the archive */
  2648.                 userec(head);
  2649.                 /* Skip to the next header on the archive */
  2650.                 skip_file((long)hstat->st_size);
  2651.                 continue;
  2652.             }
  2653.  
  2654.             (*do_something)();
  2655.             continue;
  2656.  
  2657.             /*
  2658.              * If the previous header was good, tell them
  2659.              * that we are skipping bad ones.
  2660.              */
  2661.         case 0:            /* Invalid header */
  2662.         case0:
  2663.             userec(head);
  2664.             if (prev_status == 1) {
  2665.                 annorec(stderr, tar);
  2666.                 fprintf(stderr,
  2667.                     "Skipping to next file header...\n");
  2668.             }
  2669.             continue;
  2670.  
  2671.         case 2:            /* Block of zeroes */
  2672.             if (f_ignorez)    
  2673.                 goto case0;    /* Just skip if asked */
  2674.             /* FALL THRU */
  2675.         case EOF:        /* End of archive */
  2676.             break;
  2677.         }
  2678.         break;
  2679.     };
  2680.  
  2681.     close_archive();
  2682.     names_notfound();        /* Print names not found */
  2683. }        
  2684.  
  2685.  
  2686. /*
  2687.  * Print a header record, based on tar options.
  2688.  */
  2689. void
  2690. list_archive()
  2691. {
  2692.  
  2693.     /* Save the record */
  2694.     saverec(&head);
  2695.  
  2696.     /* Print the header record */
  2697.     print_header();
  2698.  
  2699.     /* Skip past it in the archive */
  2700.     saverec((union record **) 0);    /* Unsave it */
  2701.     userec(head);
  2702.  
  2703.     /* Skip to the next header on the archive */
  2704.     skip_file((long)hstat->st_size);
  2705. }
  2706.  
  2707.  
  2708. /*
  2709.  * Read a record that's supposed to be a header record.
  2710.  * Return its address in "head", and if it is good, the file's
  2711.  * size in hstat->st_size.
  2712.  *
  2713.  * Return 1 for success, 0 if the checksum is bad, EOF on eof,
  2714.  * 2 for a block full of zeros (EOF marker).
  2715.  *
  2716.  * You must always userec(head) to skip past the header which this
  2717.  * routine reads.
  2718.  */
  2719. int
  2720. read_header()
  2721. {
  2722.     register int    i;
  2723.     register long    sum, recsum;
  2724.     register char    *p;
  2725.     register union record *header;
  2726.  
  2727.     header = findrec();
  2728.     head = header;        /* This is our current header */
  2729.     if (NULL == header) return EOF;
  2730.  
  2731.     recsum = from_oct(8,  header->header.chksum);
  2732.  
  2733.     sum = 0;
  2734.     p = header->charptr;
  2735.     for (i = sizeof(*header); --i >= 0;) {
  2736.         /*
  2737.          * We can't use unsigned char here because of old compilers,
  2738.          * e.g. V7.
  2739.          */
  2740.         sum += 0xFF & *p++;
  2741.     }
  2742.  
  2743.     /* Adjust checksum to count the "chksum" field as blanks. */
  2744.     for (i = sizeof(header->header.chksum); --i >= 0;)
  2745.         sum -= 0xFF & header->header.chksum[i];
  2746.     sum += ' '* sizeof header->header.chksum;    
  2747.  
  2748.     if (sum == recsum) {
  2749.         /*
  2750.          * Good record.  Decode file size and return.
  2751.          */
  2752.         if (header->header.linkflag == LF_LINK)
  2753.             hstat->st_size = 0;    /* Links 0 size on tape */
  2754.         else
  2755.             hstat->st_size = from_oct(1+12, header->header.size);
  2756.         return 1;
  2757.     }
  2758.  
  2759.     if (sum == 8*' ') {
  2760.         /*
  2761.          * This is a zeroed block...whole block is 0's except
  2762.          * for the 8 blanks we faked for the checksum field.
  2763.          */
  2764.         return 2;
  2765.     }
  2766.  
  2767.     return 0;
  2768. }
  2769.  
  2770.  
  2771. /* 
  2772.  * Decode things from a file header record into a "struct stat".
  2773.  * Also set "*stdp" to !=0 or ==0 depending whether header record is "Unix
  2774.  * Standard" tar format or regular old tar format.
  2775.  *
  2776.  * read_header() has already decoded the checksum and length, so we don't.
  2777.  *
  2778.  * If wantug != 0, we want the uid/group info decoded from Unix Standard
  2779.  * tapes (for extraction).  If == 0, we are just printing anyway, so save time.
  2780.  */
  2781. decode_header(header, st, stdp, wantug)
  2782.     register union record    *header;
  2783.     register struct stat    *st;
  2784.     int    *stdp;
  2785.     int    wantug;
  2786. {
  2787.  
  2788.     st->st_mode = from_oct(8,  header->header.mode);
  2789.     st->st_mtime = from_oct(1+12, header->header.mtime);
  2790.     
  2791.     if (0==strcmp(header->header.magic, TMAGIC)) {
  2792.         /* Unix Standard tar archive */
  2793.         *stdp = 1;
  2794.         if (wantug) {
  2795.             st->st_uid = finduid(header->header.uname);
  2796.             st->st_gid = findgid(header->header.gname);
  2797.         }
  2798.         switch  (header->header.linkflag) 
  2799.         case LF_BLK: case LF_CHR:
  2800.             st->st_dev = makedev(from_oct(8, header->header.devmajor),
  2801.                       from_oct(8, header->header.devminor));
  2802.     } else {
  2803.         /* Old fashioned tar archive */
  2804.         *stdp = 0;
  2805.         st->st_uid = from_oct(8,  header->header.uid);
  2806.         st->st_gid = from_oct(8,  header->header.gid);
  2807.         st->st_dev = 0;
  2808.     }
  2809. }
  2810.  
  2811.  
  2812. /*
  2813.  * Quick and dirty octal conversion.
  2814.  *
  2815.  * Result is -1 if the field is invalid (all blank, or nonoctal).
  2816.  */
  2817. long
  2818. from_oct(digs, where)
  2819.     register int    digs;
  2820.     register char    *where;
  2821. {
  2822.     register long    value;
  2823.  
  2824.     while (isspace(*where)) {        /* Skip spaces */
  2825.         where++;
  2826.         if (--digs <= 0)
  2827.             return -1;        /* All blank field */
  2828.     }
  2829.     value = 0;
  2830.     while (digs > 0 && isodigit(*where)) {    /* Scan til nonoctal */
  2831.         value = (value << 3) | (*where++ - '0');
  2832.         --digs;
  2833.     }
  2834.  
  2835.     if (digs > 0 && *where && !isspace(*where))
  2836.         return -1;            /* Ended on non-space/nul */
  2837.  
  2838.     return value;
  2839. }
  2840.  
  2841.  
  2842. /*
  2843.  * Actually print it.
  2844.  */
  2845. #define    UGSWIDTH    11        /* min width of User, group, size */
  2846. #define    DATEWIDTH    19        /* Last mod date */
  2847. static int    ugswidth = UGSWIDTH;    /* Max width encountered so far */
  2848.  
  2849. void
  2850. print_header()
  2851. {
  2852.     char modes[11];
  2853.     char *timestamp;
  2854.     char uform[11], gform[11];    /* These hold formatted ints */
  2855.     char *user, *group;
  2856.     char size[24];        /* Holds a formatted long or maj, min */
  2857.     long longie;        /* To make ctime() call portable */
  2858.     int    pad;
  2859.     int    header_std;    /* Is header standard or not? */
  2860.  
  2861.     annofile(stdout, (char *)NULL);
  2862.  
  2863.     if (f_verbose) {
  2864.         decode_header(head, hstat, &header_std, 0);
  2865.  
  2866.         /* File type and modes */
  2867.         modes[0] = '?';
  2868.         switch (head->header.linkflag) {
  2869.         case LF_NORMAL:
  2870.         case LF_OLDNORMAL:
  2871.         case LF_LINK:
  2872.                 modes[0] = '-'; 
  2873.                 if ('/' == head->header.name[strlen(head->header.name)-1])
  2874.                     modes[0] = 'd';
  2875.                 break;
  2876.         case LF_DIR:    modes[0] = 'd'; break;
  2877.         case LF_SYMLINK:modes[0] = 'l'; break;
  2878.         case LF_BLK:    modes[0] = 'b'; break;
  2879.         case LF_CHR:    modes[0] = 'c'; break;
  2880.         case LF_FIFO:    modes[0] = 'f'; break;
  2881.         case LF_CONTIG:    modes[0] = '='; break;
  2882.         }
  2883.  
  2884.         demode((unsigned)hstat->st_mode, modes+1);
  2885.  
  2886.         /* Timestamp */
  2887.         longie = hstat->st_mtime;
  2888.         timestamp = ctime(&longie);
  2889.         timestamp[16] = '\0';
  2890.         timestamp[24] = '\0';
  2891.  
  2892.         /* User and group names */
  2893.         if (*head->header.uname && header_std) {
  2894.             user  = head->header.uname;
  2895.         } else {
  2896.             user = uform;
  2897.             (void)sprintf(uform, "%d", (int)hstat->st_uid);
  2898.         }
  2899.         if (*head->header.gname && header_std) {
  2900.             group = head->header.gname;
  2901.         } else {
  2902.             group = gform;
  2903.             (void)sprintf(gform, "%d", (int)hstat->st_gid);
  2904.         }
  2905.  
  2906.         /* Format the file size or major/minor device numbers */
  2907.         switch (head->header.linkflag) {
  2908.         case LF_CHR:
  2909.         case LF_BLK:
  2910.             (void)sprintf(size, "%d, %d",
  2911.                     major(hstat->st_dev),
  2912.                     minor(hstat->st_dev));
  2913.             break;
  2914.  
  2915.         default:
  2916.             (void)sprintf(size, "%ld", (long)hstat->st_size);
  2917.         }
  2918.  
  2919.         /* Figure out padding and print the whole line. */
  2920.         pad = strlen(user) + strlen(group) + strlen(size) + 1;
  2921.         if (pad > ugswidth) ugswidth = pad;
  2922.  
  2923.         printf("%s %s/%s %*s%s %s %s %.*s",
  2924.             modes,
  2925.             user,
  2926.             group,
  2927.             ugswidth - pad,
  2928.             "",
  2929.             size,
  2930.             timestamp+4, timestamp+20,
  2931.             sizeof(head->header.name),
  2932.             head->header.name);
  2933.     } else {
  2934.         printf("%s", head->header.name);
  2935.     }
  2936.  
  2937.     if (f_verbose) switch (head->header.linkflag) {
  2938.     case LF_SYMLINK:
  2939.         printf(" -> %s\n", head->header.linkname);
  2940.         break;
  2941.  
  2942.     case LF_LINK:
  2943.         printf(" link to %s\n", head->header.linkname);
  2944.         break;
  2945.  
  2946.     default:
  2947.         printf(" unknown file type '%c'\n", head->header.linkflag);
  2948.         break;
  2949.  
  2950.     case LF_OLDNORMAL:
  2951.     case LF_NORMAL:
  2952.     case LF_CHR:
  2953.     case LF_BLK:
  2954.     case LF_DIR:
  2955.     case LF_FIFO:
  2956.     case LF_CONTIG:
  2957.         putc('\n', stdout);
  2958.         break;
  2959.     } else {
  2960.         putc('\n', stdout);
  2961.     }
  2962.  
  2963.     /* FIXME: we don't print major/minor device numbers */
  2964. }
  2965.  
  2966. /*
  2967.  * Print a similar line when we make a directory automatically.
  2968.  */
  2969. void
  2970. pr_mkdir(pathname, length, mode)
  2971.     char *pathname;
  2972.     int length;
  2973.     int mode;
  2974. {
  2975.     char modes[11];
  2976.  
  2977.     if (f_verbose) {
  2978.         /* File type and modes */
  2979.         modes[0] = 'd';
  2980.         demode((unsigned)mode, modes+1);
  2981.  
  2982.         annofile(stdout, (char *)NULL);
  2983.         printf("%s %*s %.*s\n",
  2984.             modes,
  2985.             ugswidth+DATEWIDTH,
  2986.             "Creating directory:",
  2987.             length,
  2988.             pathname);
  2989.     }
  2990. }
  2991.  
  2992.  
  2993. /*
  2994.  * Skip over <size> bytes of data in records in the archive.
  2995.  */
  2996. void
  2997. skip_file(size)
  2998.     register long size;
  2999. {
  3000.     union record *x;
  3001.  
  3002.     while (size > 0) {
  3003.         x = findrec();
  3004.         if (x == NULL) {    /* Check it... */
  3005.             annorec(stderr, tar);
  3006.             fprintf(stderr, "Unexpected EOF on archive file\n");
  3007.             exit(EX_BADARCH);
  3008.         }
  3009.         userec(x);
  3010.         size -= RECORDSIZE;
  3011.     }
  3012. }
  3013.  
  3014.  
  3015. /*
  3016.  * Decode the mode string from a stat entry into a 9-char string and a null.
  3017.  */
  3018. void
  3019. demode(mode, string)
  3020.     register unsigned mode;
  3021.     register char *string;
  3022. {
  3023.     register unsigned mask;
  3024.     register char *rwx = "rwxrwxrwx";
  3025.  
  3026.     for (mask = 0400; mask != 0; mask >>= 1) {
  3027.         if (mode & mask)
  3028.             *string++ = *rwx++;
  3029.         else {
  3030.             *string++ = '-';
  3031.             rwx++;
  3032.         }
  3033.     }
  3034.  
  3035.     if (mode & S_ISUID)
  3036.         if (string[-7] == 'x')
  3037.             string[-7] = 's';
  3038.         else
  3039.             string[-7] = 'S';
  3040.     if (mode & S_ISGID)
  3041.         if (string[-4] == 'x')
  3042.             string[-4] = 's';
  3043.         else
  3044.             string[-4] = 'S';
  3045.     if (mode & S_ISVTX)
  3046.         if (string[-1] == 'x')
  3047.             string[-1] = 't';
  3048.         else
  3049.             string[-1] = 'T';
  3050.     *string = '\0';
  3051. }
  3052. @@@ Fin de list.c
  3053. echo names.c 1>&2
  3054. cat >names.c <<'@@@ Fin de names.c'
  3055. /*
  3056.  * Look up user and/or group names.
  3057.  *
  3058.  * This file should be modified for non-unix systems to do something
  3059.  * reasonable.
  3060.  *
  3061.  * @(#)names.c 1.1 9/9/86 Public Domain - gnu
  3062.  */ 
  3063. #include <sys/types.h>
  3064. #include <pwd.h>
  3065. #include <grp.h>
  3066. #include "tar.h"
  3067.  
  3068. static int    saveuid = -993;
  3069. static char    saveuname[TUNMLEN];
  3070. static int    my_uid = -993;
  3071.  
  3072. static int    savegid = -993;
  3073. static char    savegname[TGNMLEN];
  3074. static int    my_gid = -993;
  3075.  
  3076. #define myuid    ( my_uid < 0? my_uid = getuid(): my_uid )
  3077. #define    mygid    ( my_gid < 0? my_gid = getgid(): my_gid )
  3078.  
  3079.  
  3080. #ifndef NONAMES
  3081. /*
  3082.  * Look up a user or group name from a uid/gid, maintaining a cache.
  3083.  * FIXME, for now it's a one-entry cache.
  3084.  * FIXME2, the "-993" is to reduce the chance of a hit on the first lookup.
  3085.  *
  3086.  * This is ifdef'd because on Suns, it drags in about 38K of "yellow
  3087.  * pages" code, roughly doubling the program size.  Thanks guys.
  3088.  */
  3089. void
  3090. finduname(uname, uid)
  3091.     char    uname[TUNMLEN];
  3092.     int    uid;
  3093. {
  3094.     struct passwd    *pw;
  3095.     extern struct passwd *getpwuid ();
  3096.  
  3097.     if (uid != saveuid) {
  3098.         saveuid = uid;
  3099.         saveuname[0] = '\0';
  3100.         pw = getpwuid(uid); 
  3101.         if (pw) 
  3102.             strncpy(saveuname, pw->pw_name, TUNMLEN);
  3103.     }
  3104.     strncpy(uname, saveuname, TUNMLEN);
  3105. }
  3106.  
  3107. int
  3108. finduid(uname)
  3109.     char    uname[TUNMLEN];
  3110. {
  3111.     struct passwd    *pw;
  3112.     extern struct passwd *getpwnam();
  3113.  
  3114.     if (uname[0] != saveuname[0]    /* Quick test w/o proc call */
  3115.         || 0!=strncmp(uname, saveuname, TUNMLEN)) {
  3116.         strncpy(saveuname, uname, TUNMLEN);
  3117.         pw = getpwnam(uname); 
  3118.         if (pw) {
  3119.             saveuid = pw->pw_uid;
  3120.         } else {
  3121.             saveuid = myuid;
  3122.         }
  3123.     }
  3124.     return saveuid;
  3125. }
  3126.  
  3127.  
  3128. void
  3129. findgname(gname, gid)
  3130.     char    gname[TGNMLEN];
  3131.     int    gid;
  3132. {
  3133.     struct group    *gr;
  3134.     extern struct group *getgrgid ();
  3135.  
  3136.     if (gid != savegid) {
  3137.         savegid = gid;
  3138.         savegname[0] = '\0';
  3139.         (void)setgrent();
  3140.         gr = getgrgid(gid); 
  3141.         if (gr) 
  3142.             strncpy(savegname, gr->gr_name, TGNMLEN);
  3143.     }
  3144.     (void) strncpy(gname, savegname, TGNMLEN);
  3145. }
  3146.  
  3147.  
  3148. int
  3149. findgid(gname)
  3150.     char    gname[TUNMLEN];
  3151. {
  3152.     struct group    *gr;
  3153.     extern struct group *getgrnam();
  3154.  
  3155.     if (gname[0] != savegname[0]    /* Quick test w/o proc call */
  3156.         || 0!=strncmp(gname, savegname, TUNMLEN)) {
  3157.         strncpy(savegname, gname, TUNMLEN);
  3158.         gr = getgrnam(gname); 
  3159.         if (gr) {
  3160.             savegid = gr->gr_gid;
  3161.         } else {
  3162.             savegid = mygid;
  3163.         }
  3164.     }
  3165.     return savegid;
  3166. }
  3167. #endif
  3168. @@@ Fin de names.c
  3169. echo port.c 1>&2
  3170. cat >port.c <<'@@@ Fin de port.c'
  3171. /*
  3172.  * @(#)port.c 1.6    86/08/11    Public Domain, by John Gilmore, 1986
  3173.  *
  3174.  * These are routines not available in all environments.
  3175.  *
  3176.  * I know this introduces an extra level of subroutine calls and is
  3177.  * slightly slower.  Frankly, my dear, I don't give a damn.  Let the
  3178.  * Missed-Em Vee losers suffer a little.  This software is proud to
  3179.  * have been written on a BSD system.
  3180.  */
  3181. #include <sys/types.h>
  3182. #include <sys/stat.h>
  3183. #include <signal.h>
  3184. #include <errno.h>
  3185.  
  3186. #include "port.h"
  3187.  
  3188. #ifndef BSD42
  3189. /*
  3190.  * lstat() is a stat() which does not follow symbolic links.
  3191.  * If there are no symbolic links, just use stat().
  3192.  */
  3193. int
  3194. lstat (path, buf)
  3195.     char *path;
  3196.     struct stat *buf;
  3197. {
  3198.     extern int stat ();
  3199.     return (stat (path, buf));
  3200. }
  3201.  
  3202. /*
  3203.  * valloc() does a malloc() on a page boundary.  On some systems,
  3204.  * this can make large block I/O more efficient.
  3205.  */
  3206. char *
  3207. valloc (size)
  3208.     unsigned size;
  3209. {
  3210.     extern char *malloc ();
  3211.     return (malloc (size));
  3212. }
  3213.  
  3214. /*
  3215. **                NMKDIR.C
  3216. **
  3217. ** Written by Robert Rother, Mariah Corporation, August 1985. 
  3218. **
  3219. ** I wrote this out of shear disgust with myself because I couldn't
  3220. ** figure out how to do this in /bin/sh.
  3221. **
  3222. ** If you want it, it's yours.  All I ask in return is that if you
  3223. ** figure out how to do this in a Bourne Shell script you send me
  3224. ** a copy.
  3225. **                    sdcsvax!rmr or rmr@uscd
  3226. *
  3227. * Severely hacked over by John Gilmore to make a 4.2BSD compatible
  3228. * subroutine.    11Mar86; hoptoad!gnu
  3229. */
  3230.  
  3231. /*
  3232.  * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
  3233.  */
  3234. int
  3235. mkdir(dpath, dmode)
  3236.     char *dpath;
  3237.     int dmode;
  3238. {
  3239.     int cpid, status;
  3240.     extern int errno;
  3241.  
  3242.     switch (cpid = fork()) {
  3243.  
  3244.     case -1:            /* Error in fork() */
  3245.         return(-1);        /* Errno is set already */
  3246.  
  3247.     case 0:                /* Child process */
  3248.         /*
  3249.          * Cheap hack to set mode of new directory.  Since this
  3250.          * child process is going away anyway, we zap its umask.
  3251.          * FIXME, this won't suffice to set SUID, SGID, etc. on this
  3252.          * directory.  Does anybody care?
  3253.          */
  3254.         status = umask(0);    /* Get current umask */
  3255.         status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
  3256.         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
  3257.         _exit(-1);        /* Can't exec /bin/mkdir */
  3258.     
  3259.     default:            /* Parent process */
  3260.         while (cpid != wait(&status)) ;    /* Wait for kid to finish */
  3261.     }
  3262.  
  3263.     if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
  3264.         errno = EIO;        /* We don't know why, but */
  3265.         return -1;        /* /bin/mkdir failed */
  3266.     }
  3267.  
  3268.     return 0;
  3269. }
  3270. #endif
  3271.  
  3272. #ifdef USG
  3273. /*
  3274.  * Translate V7 style into Sys V style.
  3275.  */
  3276. #include <string.h>
  3277. #include <memory.h>
  3278.  
  3279. char *
  3280. index (s, c)
  3281.     char *s;
  3282.     int c;
  3283. {
  3284.     return (strchr (s, c));
  3285. }
  3286.  
  3287. char *
  3288. bcopy (s1, s2, n)
  3289.     char *s1, *s2;
  3290.     int n;
  3291. {
  3292.     (void) memcpy (s2, s1, n);
  3293.     return (s1);
  3294. }
  3295.  
  3296. void
  3297. bzero (s1, n)
  3298.     char *s1;
  3299.     int n;
  3300. {
  3301.     (void) memset(s1, 0, n);
  3302. }
  3303. #endif
  3304. @@@ Fin de port.c
  3305. exit 0
  3306.  
  3307.