home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 May / W2KPRK.iso / apps / posix / source / PAX / CREATE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-17  |  10.1 KB  |  444 lines

  1. /* $Source: /u/mark/src/pax/RCS/create.c,v $
  2.  *
  3.  * $Revision: 1.3 $
  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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31.  *
  32.  * $Log:    create.c,v $
  33.  * Revision 1.3  89/02/12  10:29:37  mark
  34.  * Fixed misspelling of Replstr
  35.  * 
  36.  * Revision 1.2  89/02/12  10:04:17  mark
  37.  * 1.2 release fixes
  38.  * 
  39.  * Revision 1.1  88/12/23  18:02:06  mark
  40.  * Initial revision
  41.  * 
  42.  */
  43.  
  44. #ifndef lint
  45. static char *ident = "$Id: create.c,v 1.3 89/02/12 10:29:37 mark Exp Locker: mark $";
  46. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  47. #endif /* ! lint */
  48.  
  49.  
  50. /* Headers */
  51.  
  52. #include "pax.h"
  53.  
  54.  
  55. /* Function Prototypes */
  56.  
  57. #ifdef __STDC__
  58.  
  59. static void writetar(char *, Stat *);
  60. static void writecpio(char *, Stat *);
  61. #ifdef _POSIX_SOURCE  /* Xn */
  62. static char tartype(mode_t);  /* Xn */
  63. #else  /* Xn */
  64. static char tartype(int);
  65. #endif  /* Xn */
  66.  
  67. #else /* !__STDC__ */
  68.  
  69. static void writetar();
  70. static void writecpio();
  71. static char tartype();
  72.  
  73. #endif /* __STDC__ */
  74.  
  75.  
  76. /* create_archive - create a tar archive.
  77.  *
  78.  * DESCRIPTION
  79.  *
  80.  *    Create_archive is used as an entry point to both create and append
  81.  *    archives.  Create archive goes through the files specified by the
  82.  *    user and writes each one to the archive if it can.  Create_archive
  83.  *    knows how to write both cpio and tar headers and the padding which
  84.  *    is needed for each type of archive.
  85.  *
  86.  * RETURNS
  87.  *
  88.  *    Always returns 0
  89.  */
  90.  
  91. #ifdef __STDC__
  92.  
  93. int create_archive(void)
  94.  
  95. #else
  96.  
  97. int create_archive()
  98.  
  99. #endif
  100. {
  101.     char            name[PATH_MAX + 1];
  102.     Stat            sb;
  103.     int             fd;
  104.  
  105. #ifdef DF_TRACE_DEBUG
  106. printf("DF_TRACE_DEBUG: int create_archive() in create.c\n");
  107. #endif
  108.     if (f_append) {  /* Xn */
  109.     if (ar_format == TAR) {  /* Xn */
  110.         (void) lseek(archivefd, -(OFFSET) (2*blocksize), SEEK_END);  /* Xn */
  111.     } else {  /* Xn */
  112.         OFFSET  eoa;  /* Xn */
  113.   /* Xn */
  114.         eoa = lseek(archivefd, (OFFSET) 0, SEEK_CUR);  /* Xn */
  115.         (void) lseek(archivefd, -(eoa - total + 87), SEEK_END);  /* Xn */
  116.     }  /* Xn */
  117.     }  /* Xn */
  118.   /* Xn */
  119.     while (name_next(name, &sb) != -1) {
  120.     if ((fd = openin(name, &sb)) < 0) {
  121.         /* FIXME: pax wants to exit here??? */
  122.         continue;
  123.     }
  124.  
  125.     if (rplhead != (Replstr *)NULL) {
  126.         rpl_name(name);
  127.         if (strlen(name) == 0) {
  128.         continue;
  129.         }
  130.     }
  131.     if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
  132.         /* skip file... */
  133.         if (fd) {
  134.         close(fd);
  135.         }
  136.         continue;
  137.     } 
  138.  
  139.     if (!f_link && sb.sb_nlink > 1) {
  140. #if 0  /* NIST-PCTS */
  141.         if (islink(name, &sb)) {
  142. #else  /* NIST-PCTS */
  143.         if (ar_format == TAR && islink(name, &sb)) {  /* NIST-PCTS */
  144. #endif  /* NIST-PCTS */
  145.         sb.sb_size = 0;
  146.         }
  147.         linkto(name, &sb);
  148.     }
  149.     if (ar_format == TAR) {
  150.         writetar(name, &sb);
  151.     } else {
  152.         writecpio(name, &sb);
  153.     }
  154.     if (fd) {
  155.         outdata(fd, name, sb.sb_size);
  156.     }
  157.     if (f_verbose) {
  158.         print_entry(name, &sb);
  159.     }
  160.     }
  161.  
  162.     write_eot();
  163.     close_archive();
  164.     return (0);
  165. }
  166.  
  167.  
  168. /* writetar - write a header block for a tar file
  169.  *
  170.  * DESCRIPTION
  171.  *
  172.  *     Make a header block for the file name whose stat info is in st.  
  173.  *    Return header pointer for success, NULL if the name is too long.
  174.  *
  175.  *     The tar header block is structured as follows:
  176.  *
  177.  *        FIELD NAME    OFFSET        SIZE
  178.  *          -------------|---------------|------
  179.  *        name          0        100
  180.  *        mode        100          8
  181.  *        uid        108          8
  182.  *        gid        116          8
  183.  *        size        124         12
  184.  *        mtime        136         12
  185.  *        chksum        148          8
  186.  *        typeflag    156          1
  187.  *        linkname    157        100
  188.  *        magic        257          6
  189.  *        version        263          2
  190.  *        uname        265         32
  191.  *        gname        297         32
  192.  *        devmajor    329          8
  193.  *        devminor    337          8
  194.  *        prefix        345        155
  195.  *
  196.  * PARAMETERS
  197.  *
  198.  *    char    *name    - name of file to create a header block for
  199.  *    Stat    *asb    - pointer to the stat structure for the named file
  200.  *
  201.  */
  202.  
  203. #ifdef __STDC__
  204.  
  205. static void writetar(char *name, Stat *asb)
  206.  
  207. #else
  208.     
  209. static void writetar(name, asb)
  210. char           *name;
  211. Stat           *asb;
  212.  
  213. #endif
  214. {
  215.     char       *p;
  216.     char           *prefix = (char *)NULL;
  217.     int             i;
  218.     int             sum;
  219.     char            hdr[BLOCKSIZE];
  220.     Link           *from;
  221.  
  222. #ifdef DF_TRACE_DEBUG
  223. printf("DF_TRACE_DEBUG: static void writetar() in create.c\n");
  224. #endif
  225.     memset(hdr, 0, BLOCKSIZE);
  226.     if (strlen(name) > 256) {
  227.     warn(name, "name too long");
  228.     return;
  229.     }
  230.  
  231.     /* 
  232.      * If the pathname is longer than TNAMLEN, but less than 256, then
  233.      * we can split it up into the prefix and the filename.
  234.      */
  235.  
  236.     if (strlen(name) > 100) {
  237.     prefix = name;
  238.     for (;;) {
  239.         name = strchr(name + 1, '/');
  240.         if (NULL == name) {
  241.             warn(prefix, "Name too long");
  242.             return;
  243.         }
  244.  
  245.         if (strlen(name + 1) <= 100) {
  246.             *name++ = '\0';
  247.             break;
  248.         }
  249.     }
  250.     }
  251.  
  252. #ifdef S_IFLNK
  253.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  254.     strcpy(&hdr[157], asb->sb_link);
  255.     asb->sb_size = 0;
  256.     }
  257. #endif
  258.     strcpy(hdr, name);
  259.     sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
  260. #if 0
  261.     (void) fprintf(stderr, "create.c/writetar - asb->sb_uid: %lu; asb->sb_gid: %lu\n",
  262.     (unsigned long) asb->sb_uid, (unsigned long) asb->sb_gid);
  263.     (void) fflush(stderr);
  264. #endif /* Xn 1993-06-23 */
  265.     sprintf(&hdr[108], "%06o \0", asb->sb_uid);
  266.     sprintf(&hdr[116], "%06o \0", asb->sb_gid);
  267.     sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
  268.     sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
  269.     strncpy(&hdr[148], "        ", 8);
  270.     hdr[156] = tartype(asb->sb_mode);
  271.     if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
  272.  
  273.     if (strlen(from->l_name) > 100) {
  274.         warn(name, "link name too long");
  275.         return;
  276.     }
  277.  
  278.     strcpy(&hdr[157], from->l_name);
  279.     hdr[156] = LNKTYPE;
  280.     }
  281. #if 0
  282.     (void) fprintf(stderr, "create.c/writetar - name: \"%s\"; asb->sb_nlink: %lu; asb->sb_ino: %lu; asb->sb_dev: %lu; from: %p\n",
  283.     name, (unsigned long) asb->sb_nlink, (unsigned long) asb->sb_ino, (unsigned long) asb->sb_dev, from);
  284.     (void) fflush(stderr);
  285. #endif /* Xn 1993-06-21 */
  286.  
  287.     strcpy(&hdr[257], TMAGIC);
  288.     strncpy(&hdr[263], TVERSION, 2);
  289.     strcpy(&hdr[265], finduname((int) asb->sb_uid));
  290.     strcpy(&hdr[297], findgname((int) asb->sb_gid));
  291. #ifndef _POSIX_SOURCE
  292.     sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
  293.     sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
  294. #endif
  295.     if (prefix != (char *)NULL) {
  296.     strncpy(&hdr[345], prefix, 155);
  297.     }
  298.  
  299.     /* Calculate the checksum */
  300.  
  301.     sum = 0;
  302.     p = hdr;
  303.     for (i = 0; i < 500; i++) {
  304.     sum += 0xFF & *p++;
  305.     }
  306.  
  307.     /* Fill in the checksum field. */
  308.  
  309.     sprintf(&hdr[148], "%06o \0", sum);
  310.  
  311.     outwrite(hdr, BLOCKSIZE);
  312. }
  313.  
  314.  
  315. /* tartype - return tar file type from file mode
  316.  *
  317.  * DESCRIPTION
  318.  *
  319.  *    tartype returns the character which represents the type of file
  320.  *    indicated by "mode". 
  321.  *
  322.  * PARAMETERS
  323.  *
  324.  *    int    mode    - file mode from a stat block
  325.  *
  326.  * RETURNS
  327.  *
  328.  *    The character which represents the particular file type in the 
  329.  *    ustar standard headers.
  330.  */
  331.  
  332. #ifdef __STDC__
  333.  
  334. #ifdef _POSIX_SOURCE  /* Xn */
  335. static char tartype(mode_t mode)  /* Xn */
  336. #else  /* Xn */
  337. static char tartype(int mode)
  338. #endif  /* Xn */
  339.  
  340. #else
  341.     
  342. static char tartype(mode)
  343. int        mode;
  344.  
  345. #endif
  346. {
  347. #ifdef DF_TRACE_DEBUG
  348. printf("DF_TRACE_DEBUG: static char tartype() in create.c\n");
  349. #endif
  350.     switch (mode & S_IFMT) {
  351.  
  352. #ifdef S_IFCTG
  353.     case S_IFCTG:
  354.     return(CONTTYPE);
  355. #endif
  356.  
  357.     case S_IFDIR:
  358.     return (DIRTYPE);
  359.  
  360. #ifdef S_IFLNK
  361.     case S_IFLNK:
  362.     return (SYMTYPE);
  363. #endif
  364.  
  365. #ifdef S_IFIFO  /* Xn */
  366.     case S_IFIFO:
  367.     return (FIFOTYPE);
  368. #endif
  369.  
  370. #ifdef S_IFCHR
  371.     case S_IFCHR:
  372.     return (CHRTYPE);
  373. #endif
  374.  
  375. #ifdef S_IFBLK
  376.     case S_IFBLK:
  377.     return (BLKTYPE);
  378. #endif
  379.   /* Xn */
  380. #ifdef S_IFSOCK  /* Xn */
  381.     case S_IFSOCK:  /* Xn */
  382.     return (SOCKTYPE);  /* Xn */
  383. #endif  /* Xn */
  384.  
  385.     default:
  386.     return (REGTYPE);
  387.     }
  388. }
  389.  
  390.  
  391. /* writecpio - write a cpio archive header
  392.  *
  393.  * DESCRIPTION
  394.  *
  395.  *    Writes a new CPIO style archive header for the file specified.
  396.  *
  397.  * PARAMETERS
  398.  *
  399.  *    char    *name    - name of file to create a header block for
  400.  *    Stat    *asb    - pointer to the stat structure for the named file
  401.  */
  402.  
  403. #ifdef __STDC__
  404.  
  405. static void writecpio(char *name, Stat *asb)
  406.  
  407. #else
  408.     
  409. static void writecpio(name, asb)
  410. char           *name;
  411. Stat           *asb;
  412.  
  413. #endif
  414. {
  415.     uint            namelen;
  416.     char            header[M_STRLEN + H_STRLEN + 1];
  417.  
  418. #ifdef DF_TRACE_DEBUG
  419. printf("DF_TRACE_DEBUG: static void writecpio() in create.c\n");
  420. #endif
  421.     namelen = (uint) strlen(name) + 1;
  422.     strcpy(header, M_ASCII);
  423.  
  424.     sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
  425.         USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 
  426.         USH(asb->sb_uid), USH(asb->sb_gid));
  427.     sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
  428.         USH(asb->sb_nlink),
  429. #ifndef _POSIX_SOURCE
  430.         USH(asb->sb_rdev),
  431. #else
  432.         USH(0),
  433. #endif
  434.         f_mtime ? asb->sb_mtime : time((time_t *) 0),
  435.         namelen, asb->sb_size);
  436.     outwrite(header, M_STRLEN + H_STRLEN);
  437.     outwrite(name, namelen);
  438. #ifdef    S_IFLNK
  439.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  440.     outwrite(asb->sb_link, (uint) asb->sb_size);
  441.     }
  442. #endif    /* S_IFLNK */
  443. }
  444.