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