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