home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / std_unix / pax / 3 / create.c next >
Encoding:
C/C++ Source or Header  |  1989-01-07  |  7.6 KB  |  371 lines

  1. /* $Source: /u/mark/src/pax/RCS/create.c,v $
  2.  *
  3.  * $Revision: 1.1 $
  4.  *
  5.  * create.c - Create a tape archive. 
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  *    These functions are used to create/write and archive from an set of
  10.  *    named files.
  11.  *
  12.  * AUTHOR
  13.  *
  14.  *         Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  15.  *
  16.  * Sponsored by The USENIX Association for public distribution. 
  17.  *
  18.  * Copyright (c) 1989 Mark H. Colburn.
  19.  * All rights reserved.
  20.  *
  21.  * Redistribution and use in source and binary forms are permitted
  22.  * provided that the above copyright notice is duplicated in all such 
  23.  * forms and that any documentation, advertising materials, and other 
  24.  * materials related to such distribution and use acknowledge that the 
  25.  * software was developed * by Mark H. Colburn and sponsored by The 
  26.  * USENIX Association. 
  27.  *
  28.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  29.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  30.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31.  *
  32.  * $Log:    create.c,v $
  33.  * Revision 1.1  88/12/23  18:02:06  mark
  34.  * Initial revision
  35.  * 
  36.  */
  37.  
  38. #ifndef lint
  39. static char *ident = "$Id: create.c,v 1.1 88/12/23 18:02:06 mark Rel $";
  40. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  41. #endif /* ! lint */
  42.  
  43.  
  44. /* Headers */
  45.  
  46. #include "pax.h"
  47.  
  48.  
  49. /* Function Prototypes */
  50.  
  51. #ifdef __STDC__
  52.  
  53. static void writetar(char *, Stat *);
  54. static void writecpio(char *, Stat *);
  55. static char tartype(int);
  56.  
  57. #else /* !__STDC__ */
  58.  
  59. static void writetar();
  60. static void writecpio();
  61. static char tartype();
  62.  
  63. #endif /* __STDC__ */
  64.  
  65.  
  66. /* create_archive - create a tar archive.
  67.  *
  68.  * DESCRIPTION
  69.  *
  70.  *    Create_archive is used as an entry point to both create and append
  71.  *    archives.  Create archive goes through the files specified by the
  72.  *    user and writes each one to the archive if it can.  Create_archive
  73.  *    knows how to write both cpio and tar headers and the padding which
  74.  *    is needed for each type of archive.
  75.  *
  76.  * RETURNS
  77.  *
  78.  *    Always returns 0
  79.  */
  80.  
  81. #ifdef __STDC__
  82.  
  83. int create_archive(void)
  84.  
  85. #else
  86.  
  87. int create_archive()
  88.  
  89. #endif
  90. {
  91.     char            name[PATH_MAX + 1];
  92.     Stat            sb;
  93.     int             fd;
  94.  
  95.     while (name_next(name, &sb) != -1) {
  96.     if ((fd = openi(name, &sb)) < 0) {
  97.         /* FIXME: pax wants to exit here??? */
  98.         continue;
  99.     }
  100.  
  101.     if (rplhead != NULL) {
  102.         rpl_name(name);
  103.         if (strlen(name) == 0) {
  104.         continue;
  105.         }
  106.     }
  107.     if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
  108.         /* skip file... */
  109.         if (fd) {
  110.         close(fd);
  111.         }
  112.         continue;
  113.     } 
  114.  
  115.     if (!f_link && sb.sb_nlink > 1) {
  116.         if (islink(name, &sb)) {
  117.         sb.sb_size = 0;
  118.         }
  119.         linkto(name, &sb);
  120.     }
  121.     if (ar_format == TAR) {
  122.         writetar(name, &sb);
  123.     } else {
  124.         writecpio(name, &sb);
  125.     }
  126.     if (fd) {
  127.         outdata(fd, name, sb.sb_size);
  128.     }
  129.     if (f_verbose) {
  130.         print_entry(name, &sb);
  131.     }
  132.     }
  133.  
  134.     write_eot();
  135.     close_archive();
  136.     return (0);
  137. }
  138.  
  139.  
  140. /* writetar - write a header block for a tar file
  141.  *
  142.  * DESCRIPTION
  143.  *
  144.  *     Make a header block for the file name whose stat info is in st.  
  145.  *    Return header pointer for success, NULL if the name is too long.
  146.  *
  147.  *     The tar header block is structured as follows:
  148.  *
  149.  *        FIELD NAME    OFFSET        SIZE
  150.  *          -------------|---------------|------
  151.  *        name          0        100
  152.  *        mode        100          8
  153.  *        uid        108          8
  154.  *        gid        116          8
  155.  *        size        124         12
  156.  *        mtime        136         12
  157.  *        chksum        148          8
  158.  *        typeflag    156          1
  159.  *        linkname    157        100
  160.  *        magic        257          6
  161.  *        version        263          2
  162.  *        uname        265         32
  163.  *        gname        297         32
  164.  *        devmajor    329          8
  165.  *        devminor    337          8
  166.  *        prefix        345        155
  167.  *
  168.  * PARAMETERS
  169.  *
  170.  *    char    *name    - name of file to create a header block for
  171.  *    Stat    *asb    - pointer to the stat structure for the named file
  172.  *
  173.  */
  174.  
  175. #ifdef __STDC__
  176.  
  177. static void writetar(char *name, Stat *asb)
  178.  
  179. #else
  180.     
  181. static void writetar(name, asb)
  182. char           *name;
  183. Stat           *asb;
  184.  
  185. #endif
  186. {
  187.     char       *p;
  188.     char           *prefix = NULL;
  189.     int             i;
  190.     int             sum;
  191.     char            hdr[BLOCKSIZE];
  192.     Link           *from;
  193.  
  194.     memset(hdr, 0, BLOCKSIZE);
  195.     if (strlen(name) > 255) {
  196.     warn(name, "name too long");
  197.     return;
  198.     }
  199.  
  200.     /* 
  201.      * If the pathname is longer than TNAMLEN, but less than 255, then
  202.      * we can split it up into the prefix and the filename.
  203.      */
  204.     if (strlen(name) > 100) {
  205.     prefix = name;
  206.     name += 155;
  207.     while (name > prefix && *name != '/') {
  208.         name--;
  209.     }
  210.  
  211.     /* no slash found....hmmm.... */
  212.     if (name == prefix) {
  213.         warn(prefix, "Name too long");
  214.         return;
  215.     }
  216.     *name++ = '\0';
  217.     }
  218.  
  219. #ifdef S_IFLNK
  220.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  221.     strcpy(&hdr[157], asb->sb_link);
  222.     asb->sb_size = 0;
  223.     }
  224. #endif
  225.     strcpy(hdr, name);
  226.     sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
  227.     sprintf(&hdr[108], "%06o \0", asb->sb_uid);
  228.     sprintf(&hdr[116], "%06o \0", asb->sb_gid);
  229.     sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
  230.     sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
  231.     strncpy(&hdr[148], "        ", 8);
  232.     hdr[156] = tartype(asb->sb_mode);
  233.     if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != NULL) {
  234.     strcpy(&hdr[157], from->l_name);
  235.     hdr[156] = LNKTYPE;
  236.     }
  237.     strcpy(&hdr[257], TMAGIC);
  238.     strncpy(&hdr[263], TVERSION, 2);
  239.     strcpy(&hdr[265], finduname((int) asb->sb_uid));
  240.     strcpy(&hdr[297], findgname((int) asb->sb_gid));
  241.     sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
  242.     sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
  243.     if (prefix != NULL) {
  244.     strncpy(&hdr[345], prefix, 155);
  245.     }
  246.  
  247.     /* Calculate the checksum */
  248.  
  249.     sum = 0;
  250.     p = hdr;
  251.     for (i = 0; i < 500; i++) {
  252.     sum += 0xFF & *p++;
  253.     }
  254.  
  255.     /* Fill in the checksum field. */
  256.  
  257.     sprintf(&hdr[148], "%06o \0", sum);
  258.  
  259.     outwrite(hdr, BLOCKSIZE);
  260. }
  261.  
  262.  
  263. /* tartype - return tar file type from file mode
  264.  *
  265.  * DESCRIPTION
  266.  *
  267.  *    tartype returns the character which represents the type of file
  268.  *    indicated by "mode". 
  269.  *
  270.  * PARAMETERS
  271.  *
  272.  *    int    mode    - file mode from a stat block
  273.  *
  274.  * RETURNS
  275.  *
  276.  *    The character which represents the particular file type in the 
  277.  *    ustar standard headers.
  278.  */
  279.  
  280. #ifdef __STDC__
  281.  
  282. static char tartype(int mode)
  283.  
  284. #else
  285.     
  286. static char tartype(mode)
  287. int        mode;
  288.  
  289. #endif
  290. {
  291.     switch (mode & S_IFMT) {
  292.  
  293. #ifdef S_IFCTG
  294.     case S_IFCTG:
  295.     return(CONTTYPE);
  296. #endif
  297.  
  298.     case S_IFDIR:
  299.     return (DIRTYPE);
  300.  
  301. #ifdef S_IFLNK
  302.     case S_IFLNK:
  303.     return (SYMTYPE);
  304. #endif
  305.  
  306. #ifdef S_IFFIFO
  307.     case S_IFIFO:
  308.     return (FIFOTYPE);
  309. #endif
  310.  
  311. #ifdef S_IFCHR
  312.     case S_IFCHR:
  313.     return (CHRTYPE);
  314. #endif
  315.  
  316. #ifdef S_IFBLK
  317.     case S_IFBLK:
  318.     return (BLKTYPE);
  319. #endif
  320.  
  321.     default:
  322.     return (REGTYPE);
  323.     }
  324. }
  325.  
  326.  
  327. /* writecpio - write a cpio archive header
  328.  *
  329.  * DESCRIPTION
  330.  *
  331.  *    Writes a new CPIO style archive header for the file specified.
  332.  *
  333.  * PARAMETERS
  334.  *
  335.  *    char    *name    - name of file to create a header block for
  336.  *    Stat    *asb    - pointer to the stat structure for the named file
  337.  */
  338.  
  339. #ifdef __STDC__
  340.  
  341. static void writecpio(char *name, Stat *asb)
  342.  
  343. #else
  344.     
  345. static void writecpio(name, asb)
  346. char           *name;
  347. Stat           *asb;
  348.  
  349. #endif
  350. {
  351.     uint            namelen;
  352.     char            header[M_STRLEN + H_STRLEN + 1];
  353.  
  354.     namelen = (uint) strlen(name) + 1;
  355.     strcpy(header, M_ASCII);
  356.     sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
  357.         USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 
  358.         USH(asb->sb_uid), USH(asb->sb_gid));
  359.     sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
  360.         USH(asb->sb_nlink), USH(asb->sb_rdev),
  361.         f_modification_time ? asb->sb_mtime : time((time_t *) 0),
  362.         namelen, asb->sb_size);
  363.     outwrite(header, M_STRLEN + H_STRLEN);
  364.     outwrite(name, namelen);
  365. #ifdef    S_IFLNK
  366.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  367.     outwrite(asb->sb_link, (uint) asb->sb_size);
  368.     }
  369. #endif    /* S_IFLNK */
  370. }
  371.