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