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

  1. /* $Source: /u/mark/src/pax/RCS/fileio.c,v $
  2.  *
  3.  * $Revision: 1.2 $
  4.  *
  5.  * fileio.c - file I/O functions for all archive interfaces
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  *    These function all do I/O of some form or another.  They are
  10.  *    grouped here mainly for convienence.
  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:    fileio.c,v $
  33.  * Revision 1.2  89/02/12  10:04:31  mark
  34.  * 1.2 release fixes
  35.  * 
  36.  * Revision 1.1  88/12/23  18:02:09  mark
  37.  * Initial revision
  38.  * 
  39.  */
  40.  
  41. #ifndef lint
  42. static char *ident = "$Id: fileio.c,v 1.2 89/02/12 10:04:31 mark Exp $";
  43. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  44. #endif /* ! lint */
  45.  
  46.  
  47. /* Headers */
  48.  
  49. #include "pax.h"
  50.  
  51.  
  52. /* open_archive -  open an archive file.  
  53.  *
  54.  * DESCRIPTION
  55.  *
  56.  *    Open_archive will open an archive file for reading or writing,
  57.  *    setting the proper file mode, depending on the "mode" passed to
  58.  *    it.  All buffer pointers are reset according to the mode
  59.  *    specified.
  60.  *
  61.  * PARAMETERS
  62.  *
  63.  *     int    mode     - specifies whether we are reading or writing.   
  64.  *
  65.  * RETURNS
  66.  *
  67.  *    Returns a zero if successfull, or -1 if an error occured during 
  68.  *    the open.
  69.  */
  70.  
  71. #ifdef __STDC__
  72.     
  73. int open_archive(int mode)
  74.  
  75. #else
  76.     
  77. int open_archive(mode)
  78. int             mode;
  79.  
  80. #endif
  81. {
  82. #ifdef DF_TRACE_DEBUG
  83. printf("DF_TRACE_DEBUG: int open_archive() in fileio.c\n");
  84. #endif
  85.     if (ar_file[0] == '-' && ar_file[1] == '\0') {
  86.     if (mode == AR_READ) {
  87.         archivefd = STDIN;
  88.         bufend = bufidx = bufstart;
  89.     } else {
  90.         archivefd = STDOUT;
  91.     }
  92.     } else if (mode == AR_READ) {
  93.     archivefd = open(ar_file, O_RDONLY | O_BINARY);
  94.     bufend = bufidx = bufstart;    /* set up for initial read */
  95.     } else if (mode == AR_WRITE) {
  96.     archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY,  /* Xn */
  97.         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);  /* Xn */
  98.     } else if (mode == AR_APPEND) {
  99.     archivefd = open(ar_file, O_RDWR | O_BINARY,  /* Xn */
  100.         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);  /* Xn */
  101.     bufend = bufidx = bufstart;    /* set up for initial read */
  102.     }
  103.  
  104.     if (archivefd < 0) {
  105.     warnarch(strerror(errno), (OFFSET) 0);  /* Xn */
  106.     return (-1);
  107.     }
  108.     ++arvolume;
  109.     return (0);
  110. }
  111.  
  112.  
  113. /* close_archive - close the archive file
  114.  *
  115.  * DESCRIPTION
  116.  *
  117.  *    Closes the current archive and resets the archive end of file
  118.  *    marker.
  119.  */
  120.  
  121. #ifdef __STDC__
  122.  
  123. void close_archive(void)
  124.  
  125. #else
  126.     
  127. void close_archive()
  128.  
  129. #endif
  130. {
  131. #ifdef DF_TRACE_DEBUG
  132. printf("DF_TRACE_DEBUG: void close_archive() in fileio.c\n");
  133. #endif
  134.     if (archivefd != STDIN && archivefd != STDOUT) {
  135.     close(archivefd);
  136.     }
  137.     areof = 0;
  138. }
  139.  
  140.  
  141. /* openout - open an output file
  142.  *
  143.  * DESCRIPTION
  144.  *
  145.  *    Openo opens the named file for output.  The file mode and type are
  146.  *    set based on the values stored in the stat structure for the file.
  147.  *    If the file is a special file, then no data will be written, the
  148.  *    file/directory/Fifo, etc., will just be created.  Appropriate
  149.  *    permission may be required to create special files.
  150.  *
  151.  * PARAMETERS
  152.  *
  153.  *    char     *name        - The name of the file to create
  154.  *    Stat    *asb        - Stat structure for the file
  155.  *    Link    *linkp;        - pointer to link chain for this file
  156.  *    int     ispass        - true if we are operating in "pass" mode
  157.  *
  158.  * RETURNS
  159.  *
  160.  *     Returns the output file descriptor, 0 if no data is required or -1 
  161.  *    if unsuccessful. Note that UNIX open() will never return 0 because 
  162.  *    the standard input is in use. 
  163.  */
  164.  
  165. #ifdef __STDC__
  166.  
  167. int openout(char *name, Stat *asb, Link *linkp, int ispass)
  168.  
  169. #else
  170.     
  171. int openout(name, asb, linkp, ispass)
  172. char           *name;
  173. Stat           *asb;
  174. Link           *linkp;
  175. int             ispass;
  176.  
  177. #endif
  178. {
  179.     int             exists;
  180.     int             fd;
  181. #ifdef _POSIX_SOURCE  /* Xn */
  182.     mode_t          perm;  /* Xn */
  183.     mode_t          operm = (mode_t)0;  /* Xn */
  184. #else  /* Xn */
  185.     ushort          perm;
  186.     ushort          operm = 0;
  187. #endif  /* Xn */
  188.     Stat            osb;
  189. #ifdef    S_IFLNK
  190.     int             ssize;
  191.     char            sname[PATH_MAX + 1];
  192. #endif    /* S_IFLNK */
  193.  
  194. #ifdef DF_TRACE_DEBUG
  195. printf("DF_TRACE_DEBUG: int openout() in fileio.c\n");
  196. #endif
  197.     if ((exists = (LSTAT(name, &osb) == 0)) != 0) {  /* Xn */
  198.     if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
  199.         warn(name, "Same file");
  200.         return (-1);
  201.     } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
  202.         operm = osb.sb_mode & S_IPERM;
  203.     } else if (REMOVE(name, &osb) < 0) {
  204.         warn(name, strerror(errno));  /* Xn */
  205.         return (-1);
  206.     } else {
  207.         exists = 0;
  208.     }
  209.     }
  210.     if (linkp) {
  211.     if (exists) {
  212.         if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
  213.         return (0);
  214.         } else if (unlink(name) < 0) {
  215.         warn(name, strerror(errno));  /* Xn */
  216.         return (-1);
  217.         } else {
  218.         exists = 0;
  219.         }
  220.     }
  221.     if (link(linkp->l_name, name) != 0) {
  222.         if (errno == ENOENT) {
  223.         if (f_dir_create) {
  224.             if (dirneed(name) != 0 ||
  225.                 link(linkp->l_name, name) != 0) {
  226.                 warn(name, strerror(errno));  /* Xn */
  227.             return (-1);
  228.             }
  229.         } else {
  230.             warn(name, 
  231.                  "Directories are not being created (-d option)");
  232.         }
  233.         return(0);
  234.         } else if (errno != EXDEV) {
  235.         warn(name, strerror(errno));  /* Xn */
  236.         return (-1);
  237.         }
  238.     } else {
  239.         return(0);
  240.     } 
  241.     }
  242.     perm = asb->sb_mode & S_IPERM;
  243.     switch (asb->sb_mode & S_IFMT) {
  244.     case S_IFBLK:
  245.     case S_IFCHR:
  246.     fd = 0;
  247.     if (exists) {
  248. #ifndef _POSIX_SOURCE
  249.         if (asb->sb_rdev == osb.sb_rdev) {
  250.         if (perm != operm && chmod(name, (int) perm) < 0) {
  251.             warn(name, strerror(errno));  /* Xn */
  252.             return (-1);
  253.         } else {
  254.             break;
  255.         }
  256.         } else if (REMOVE(name, &osb) < 0) {
  257.         warn(name, strerror(errno));  /* Xn */
  258.         return (-1);
  259.         } else {
  260.         exists = 0;
  261.         }
  262. #else
  263.         if (REMOVE(name, &osb) < 0) {
  264.         warn(name, strerror(errno));  /* Xn */
  265.         return (-1);
  266.         } else {
  267.         exists = 0;
  268.         }
  269. #endif /* _POSIX_SOURCE */
  270.     }
  271. #ifdef _POSIX_SOURCE
  272.     if (mknod(name, asb->sb_mode, (dev_t)0))
  273. #else
  274.     if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0)
  275. #endif
  276.     {
  277.         if (errno == ENOENT) {
  278.         if (f_dir_create) {
  279.             if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode, 
  280. #ifdef _POSIX_SOURCE
  281.                0))
  282. #else
  283.                (int) asb->sb_rdev) < 0)
  284. #endif
  285.             {
  286.             warn(name, strerror(errno));  /* Xn */
  287.             return (-1);
  288.             }
  289.         } else {
  290.             warn(name, "Directories are not being created (-d option)");
  291.         }
  292.         } else {
  293.         warn(name, strerror(errno));  /* Xn */
  294.         return (-1);
  295.         }
  296.     }
  297.     return(0);
  298.     break;
  299.     case S_IFDIR:
  300.     if (exists) {
  301.         if (perm != operm && chmod(name, (int) perm) < 0) {
  302.         warn(name, strerror(errno));  /* Xn */
  303.         return (-1);
  304.         }
  305.     } else if (f_dir_create) {
  306.         if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
  307.         warn(name, strerror(errno));  /* Xn */
  308.         return (-1);
  309.         }
  310.     } else {
  311.         warn(name, "Directories are not being created (-d option)");
  312.     }
  313.     return (0);
  314. #ifdef    S_IFIFO
  315.     case S_IFIFO:
  316.     fd = 0;
  317.     if (exists) {
  318.         if (perm != operm && chmod(name, (int) perm) < 0) {
  319.         warn(name, strerror(errno));  /* Xn */
  320.         return (-1);
  321.         }
  322.     }
  323. # ifdef    _POSIX_SOURCE  /* Xn */
  324.     else if (mkfifo(name, asb->sb_mode) < 0)  /* Xn */
  325. # else  /* Xn */
  326.     else if (mknod(name, (int) asb->sb_mode, 0) < 0)
  327. # endif  /* Xn */
  328.     {
  329.         if (errno == ENOENT) {
  330.         if (f_dir_create) {
  331.             if (dirneed(name) < 0
  332. # ifdef    _POSIX_SOURCE  /* Xn */
  333.                || mkfifo(name, asb->sb_mode) < 0)  /* Xn */
  334. # else  /* Xn */
  335.                || mknod(name, (int) asb->sb_mode, 0) < 0)
  336. # endif    /* _POSIX_SOURCE */  /* Xn */
  337.             {
  338.             warn(name, strerror(errno));  /* Xn */
  339.             return (-1);
  340.             }
  341.         } else {
  342.             warn(name, "Directories are not being created (-d option)");
  343.         }
  344.         } else {
  345.         warn(name, strerror(errno));  /* Xn */
  346.         return (-1);
  347.         }
  348.     }
  349.     return(0);
  350.     break;
  351. #endif                /* S_IFIFO */
  352. #ifdef    S_IFLNK
  353.     case S_IFLNK:
  354.     if (exists) {
  355.         if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
  356.         warn(name, strerror(errno));  /* Xn */
  357.         return (-1);
  358.         } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
  359.         return (0);
  360.         } else if (REMOVE(name, &osb) < 0) {
  361.         warn(name, strerror(errno));  /* Xn */
  362.         return (-1);
  363.         } else {
  364.         exists = 0;
  365.         }
  366.     }
  367.     if (symlink(asb->sb_link, name) < 0) {
  368.         if (errno == ENOENT) {
  369.         if (f_dir_create) {
  370.             if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
  371.             warn(name, strerror(errno));  /* Xn */
  372.             return (-1);
  373.             }
  374.         } else {
  375.             warn(name, "Directories are not being created (-d option)");
  376.         }
  377.         } else {
  378.         warn(name, strerror(errno));  /* Xn */
  379.         return (-1);
  380.         }
  381.     }
  382.     return (0);        /* Can't chown()/chmod() a symbolic link */
  383. #endif                /* S_IFLNK */
  384.     case S_IFREG:
  385.     if (exists) {
  386.         if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
  387.         warn(name, "Newer file exists");
  388.         return (-1);
  389.         } else if (unlink(name) < 0) {
  390.         warn(name, strerror(errno));  /* Xn */
  391.         return (-1);
  392.         } else {
  393.         exists = 0;
  394.         }
  395.     }
  396.     if ((fd = creat(name, (int) perm)) < 0) {
  397.         if (errno == ENOENT) {
  398.         if (f_dir_create) {
  399.             if (dirneed(name) < 0 || 
  400.                 (fd = creat(name, (int) perm)) < 0) {
  401.             warn(name, strerror(errno));  /* Xn */
  402.             return (-1);
  403.             }
  404.         } else {
  405.             /* 
  406.              * the file requires a directory which does not exist
  407.              * and which the user does not want created, so skip
  408.              * the file...
  409.              */
  410.             warn(name, "Directories are not being created (-d option)");
  411.             return(0);
  412.         }
  413.         } else {
  414.         warn(name, strerror(errno));  /* Xn */
  415.         return (-1);
  416.         }
  417.     }
  418.     break;
  419.     default:
  420.     warn(name, "Unknown filetype");
  421.     return (-1);
  422.     }
  423.     if (f_owner) {
  424.     if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
  425.         chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
  426.     }
  427.     }
  428.     return (fd);
  429. }
  430.  
  431.  
  432. /* openin - open the next input file
  433.  *
  434.  * DESCRIPTION
  435.  *
  436.  *    Openi will attempt to open the next file for input.  If the file is
  437.  *    a special file, such as a directory, FIFO, link, character- or
  438.  *    block-special file, then the file size field of the stat structure
  439.  *    is zeroed to make sure that no data is written out for the file.
  440.  *    If the file is a special file, then a file descriptor of 0 is
  441.  *    returned to the caller, which is handled specially.  If the file
  442.  *    is a regular file, then the file is opened and a file descriptor
  443.  *    to the open file is returned to the caller.
  444.  *
  445.  * PARAMETERS
  446.  *
  447.  *    char   *name    - pointer to the name of the file to open
  448.  *    Stat   *asb    - pointer to the stat block for the file to open
  449.  *
  450.  * RETURNS
  451.  *
  452.  *     Returns a file descriptor, 0 if no data exists, or -1 at EOF. This 
  453.  *    kludge works because standard input is in use, preventing open() from 
  454.  *    returning zero. 
  455.  */
  456.  
  457. #ifdef __STDC__
  458.  
  459. int openin(char *name, Stat *asb)
  460.  
  461. #else
  462.     
  463. int openin(name, asb)
  464. char           *name;        /* name of file to open */
  465. Stat           *asb;        /* pointer to stat structure for file */
  466.  
  467. #endif
  468. {
  469.     int             fd;
  470.  
  471. #ifdef DF_TRACE_DEBUG
  472. printf("DF_TRACE_DEBUG: int openin() in fileio.c\n");
  473. #endif
  474.     switch (asb->sb_mode & S_IFMT) {
  475.     case S_IFDIR:
  476. #if 0  /* NIST-PCTS */
  477.     asb->sb_nlink = 1;
  478. #endif  /* NIST-PCTS */
  479.     asb->sb_size = 0;
  480.     return (0);
  481. #ifdef    S_IFLNK
  482.     case S_IFLNK:
  483.     if ((asb->sb_size = readlink(name,
  484.                  asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
  485.         warn(name, strerror(errno));  /* Xn */
  486.         return(0);
  487.     }
  488.     asb->sb_link[asb->sb_size] = '\0';
  489.     return (0);
  490. #endif                /* S_IFLNK */
  491.     case S_IFREG:
  492.     if (asb->sb_size == 0) {
  493.         return (0);
  494.     }
  495.     if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
  496.         warn(name, strerror(errno));  /* Xn */
  497.     }
  498.     return (fd);
  499.     default:
  500.     asb->sb_size = 0;
  501.     return (0);
  502.     }
  503. }
  504.