|
|
1.1 ! root 1: /* $Source: /src386/usr/bin/pax/create.c,v $ ! 2: * ! 3: * $Revision: 1.1 $ ! 4: * ! 5: * create.c - Create a tape archive. ! 6: * ! 7: * DESCRIPTION ! 8: * ! 9: * These functions are used to create/write and archive from an set of ! 10: * named files. ! 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: create.c,v $ ! 33: * Revision 1.1 92/08/28 08:02:01 bin ! 34: * Initial revision ! 35: * ! 36: * Revision 1.1 89/02/14 16:47:48 jep ! 37: * Initial revision ! 38: * ! 39: * Revision 1.1 88/12/23 18:02:06 mark ! 40: * Initial revision ! 41: * ! 42: */ ! 43: ! 44: #ifndef lint ! 45: static char *ident = "$Id: create.c,v 1.1 92/08/28 08:02:01 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: ! 55: /* Function Prototypes */ ! 56: ! 57: #if __STDC__ ! 58: ! 59: static void writetar(char *, Stat *); ! 60: static void writecpio(char *, Stat *); ! 61: static char tartype(int); ! 62: ! 63: #else /* !__STDC__ */ ! 64: ! 65: static void writetar(); ! 66: static void writecpio(); ! 67: static char tartype(); ! 68: ! 69: #endif /* __STDC__ */ ! 70: ! 71: ! 72: /* create_archive - create a tar archive. ! 73: * ! 74: * DESCRIPTION ! 75: * ! 76: * Create_archive is used as an entry point to both create and append ! 77: * archives. Create archive goes through the files specified by the ! 78: * user and writes each one to the archive if it can. Create_archive ! 79: * knows how to write both cpio and tar headers and the padding which ! 80: * is needed for each type of archive. ! 81: * ! 82: * RETURNS ! 83: * ! 84: * Always returns 0 ! 85: */ ! 86: ! 87: #if __STDC__ ! 88: ! 89: int create_archive(void) ! 90: ! 91: #else ! 92: ! 93: int create_archive() ! 94: ! 95: #endif ! 96: { ! 97: char name[PATH_MAX + 1]; ! 98: Stat sb; ! 99: int fd; ! 100: ! 101: while (name_next(name, &sb) != -1) { ! 102: if ((fd = openin(name, &sb)) < 0) { ! 103: /* FIXME: pax wants to exit here??? */ ! 104: continue; ! 105: } ! 106: ! 107: if (rplhead != (Replstr *)NULL) { ! 108: rpl_name(name); ! 109: if (strlen(name) == 0) { ! 110: continue; ! 111: } ! 112: } ! 113: if (get_disposition("add", name) || get_newname(name, sizeof(name))) { ! 114: /* skip file... */ ! 115: if (fd) { ! 116: close(fd); ! 117: } ! 118: continue; ! 119: } ! 120: ! 121: if (!f_link && sb.sb_nlink > 1) { ! 122: if (islink(name, &sb)) { ! 123: sb.sb_size = 0; ! 124: } ! 125: linkto(name, &sb); ! 126: } ! 127: if (ar_format == TAR) { ! 128: /* SV tar does not understand POSIX tar header. ! 129: * Trailing '/' in directory name alows SV tar to unarchive ! 130: * POSIX tar archive. So, we add '/' to the "name" if it is ! 131: * a directory name. ! 132: * SV tar will produce error messages, but ! 133: * will do the job. Vlad 11-8-91 ! 134: */ ! 135: if ((sb.sb_stat.st_mode & S_IFMT) == S_IFDIR) { ! 136: int il; ! 137: ! 138: il = strlen(name); ! 139: name[il++] = '/'; ! 140: name[il] = 0; ! 141: } ! 142: writetar(name, &sb); ! 143: } else { ! 144: writecpio(name, &sb); ! 145: } ! 146: if (fd) { ! 147: outdata(fd, name, sb.sb_size); ! 148: } ! 149: if (f_verbose) { ! 150: print_entry(name, &sb); ! 151: } ! 152: } ! 153: ! 154: write_eot(); ! 155: close_archive(); ! 156: return (0); ! 157: } ! 158: ! 159: ! 160: /* writetar - write a header block for a tar file ! 161: * ! 162: * DESCRIPTION ! 163: * ! 164: * Make a header block for the file name whose stat info is in st. ! 165: * Return header pointer for success, NULL if the name is too long. ! 166: * ! 167: * The tar header block is structured as follows: ! 168: * ! 169: * FIELD NAME OFFSET SIZE ! 170: * -------------|---------------|------ ! 171: * name 0 100 ! 172: * mode 100 8 ! 173: * uid 108 8 ! 174: * gid 116 8 ! 175: * size 124 12 ! 176: * mtime 136 12 ! 177: * chksum 148 8 ! 178: * typeflag 156 1 ! 179: * linkname 157 100 ! 180: * magic 257 6 ! 181: * version 263 2 ! 182: * uname 265 32 ! 183: * gname 297 32 ! 184: * devmajor 329 8 ! 185: * devminor 337 8 ! 186: * prefix 345 155 ! 187: * ! 188: * PARAMETERS ! 189: * ! 190: * char *name - name of file to create a header block for ! 191: * Stat *asb - pointer to the stat structure for the named file ! 192: * ! 193: */ ! 194: ! 195: #if __STDC__ ! 196: ! 197: static void writetar(char *name, Stat *asb) ! 198: ! 199: #else ! 200: ! 201: static void writetar(name, asb) ! 202: char *name; ! 203: Stat *asb; ! 204: ! 205: #endif ! 206: { ! 207: char *p; ! 208: char *prefix = (char *)NULL; ! 209: int i; ! 210: int sum; ! 211: char hdr[BLOCKSIZE]; ! 212: Link *from; ! 213: ! 214: memset(hdr, 0, BLOCKSIZE); ! 215: if (strlen(name) > 255) { ! 216: warn(name, "name too long"); ! 217: return; ! 218: } ! 219: ! 220: /* ! 221: * If the pathname is longer than TNAMLEN, but less than 255, then ! 222: * we can split it up into the prefix and the filename. ! 223: */ ! 224: if (strlen(name) > 100) { ! 225: prefix = name; ! 226: name += 155; ! 227: while (name > prefix && *name != '/') { ! 228: name--; ! 229: } ! 230: ! 231: /* no slash found....hmmm.... */ ! 232: if (name == prefix) { ! 233: warn(prefix, "Name too long"); ! 234: return; ! 235: } ! 236: *name++ = '\0'; ! 237: } ! 238: ! 239: #ifdef S_IFLNK ! 240: if ((asb->sb_mode & S_IFMT) == S_IFLNK) { ! 241: strcpy(&hdr[157], asb->sb_link); ! 242: asb->sb_size = 0; ! 243: } ! 244: #endif ! 245: strcpy(hdr, name); ! 246: sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT); ! 247: sprintf(&hdr[108], "%06o \0", asb->sb_uid); ! 248: sprintf(&hdr[116], "%06o \0", asb->sb_gid); ! 249: sprintf(&hdr[124], "%011lo ", (long) asb->sb_size); ! 250: sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime); ! 251: strncpy(&hdr[148], " ", 8); ! 252: hdr[156] = tartype(asb->sb_mode); ! 253: if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) { ! 254: strcpy(&hdr[157], from->l_name); ! 255: hdr[156] = LNKTYPE; ! 256: } ! 257: strcpy(&hdr[257], TMAGIC); ! 258: strncpy(&hdr[263], TVERSION, 2); ! 259: strcpy(&hdr[265], finduname((int) asb->sb_uid)); ! 260: strcpy(&hdr[297], findgname((int) asb->sb_gid)); ! 261: sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev)); ! 262: sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev)); ! 263: if (prefix != (char *)NULL) { ! 264: strncpy(&hdr[345], prefix, 155); ! 265: } ! 266: ! 267: /* Calculate the checksum */ ! 268: ! 269: sum = 0; ! 270: p = hdr; ! 271: for (i = 0; i < 500; i++) { ! 272: sum += 0xFF & *p++; ! 273: } ! 274: ! 275: /* Fill in the checksum field. */ ! 276: ! 277: sprintf(&hdr[148], "%06o \0", sum); ! 278: ! 279: outwrite(hdr, BLOCKSIZE); ! 280: } ! 281: ! 282: ! 283: /* tartype - return tar file type from file mode ! 284: * ! 285: * DESCRIPTION ! 286: * ! 287: * tartype returns the character which represents the type of file ! 288: * indicated by "mode". ! 289: * ! 290: * PARAMETERS ! 291: * ! 292: * int mode - file mode from a stat block ! 293: * ! 294: * RETURNS ! 295: * ! 296: * The character which represents the particular file type in the ! 297: * ustar standard headers. ! 298: */ ! 299: ! 300: #if __STDC__ ! 301: ! 302: static char tartype(int mode) ! 303: ! 304: #else ! 305: ! 306: static char tartype(mode) ! 307: int mode; ! 308: ! 309: #endif ! 310: { ! 311: switch (mode & S_IFMT) { ! 312: ! 313: #ifdef S_IFCTG ! 314: case S_IFCTG: ! 315: return(CONTTYPE); ! 316: #endif ! 317: ! 318: case S_IFDIR: ! 319: return (DIRTYPE); ! 320: ! 321: #ifdef S_IFLNK ! 322: case S_IFLNK: ! 323: return (SYMTYPE); ! 324: #endif ! 325: ! 326: #ifdef S_IFFIFO ! 327: case S_IFIFO: ! 328: return (FIFOTYPE); ! 329: #endif ! 330: ! 331: #ifdef S_IFCHR ! 332: case S_IFCHR: ! 333: return (CHRTYPE); ! 334: #endif ! 335: ! 336: #ifdef S_IFBLK ! 337: case S_IFBLK: ! 338: return (BLKTYPE); ! 339: #endif ! 340: ! 341: default: ! 342: return (REGTYPE); ! 343: } ! 344: } ! 345: ! 346: ! 347: /* writecpio - write a cpio archive header ! 348: * ! 349: * DESCRIPTION ! 350: * ! 351: * Writes a new CPIO style archive header for the file specified. ! 352: * ! 353: * PARAMETERS ! 354: * ! 355: * char *name - name of file to create a header block for ! 356: * Stat *asb - pointer to the stat structure for the named file ! 357: */ ! 358: ! 359: #if __STDC__ ! 360: ! 361: static void writecpio(char *name, Stat *asb) ! 362: ! 363: #else ! 364: ! 365: static void writecpio(name, asb) ! 366: char *name; ! 367: Stat *asb; ! 368: ! 369: #endif ! 370: { ! 371: uint namelen; ! 372: char header[M_STRLEN + H_STRLEN + 1]; ! 373: ! 374: namelen = (uint) strlen(name) + 1; ! 375: strcpy(header, M_ASCII); ! 376: sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o", ! 377: USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), ! 378: USH(asb->sb_uid), USH(asb->sb_gid)); ! 379: sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo", ! 380: USH(asb->sb_nlink), USH(asb->sb_rdev), ! 381: f_mtime ? asb->sb_mtime : time((time_t *) 0), ! 382: namelen, asb->sb_size); ! 383: outwrite(header, M_STRLEN + H_STRLEN); ! 384: outwrite(name, namelen); ! 385: #ifdef S_IFLNK ! 386: if ((asb->sb_mode & S_IFMT) == S_IFLNK) { ! 387: outwrite(asb->sb_link, (uint) asb->sb_size); ! 388: } ! 389: #endif /* S_IFLNK */ ! 390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.