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

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