home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / PAX20.ZIP / CREATE.C < prev    next >
C/C++ Source or Header  |  1990-11-12  |  10KB  |  409 lines

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