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

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