1 /* $Source: /u/mark/src/pax/RCS/create.c,v $ 2 * 3 * $Revision: 1.3 $ 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 (mark@jhereg.mn.org) 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.3 89/02/12 10:29:37 mark 34 * Fixed misspelling of Replstr 35 * 36 * Revision 1.2 89/02/12 10:04:17 mark 37 * 1.2 release fixes 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.3 89/02/12 10:29:37 mark Exp Locker: mark $"; 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 #ifdef __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 #ifdef __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 writetar(name, &sb); 129 } else { 130 writecpio(name, &sb); 131 } 132 if (fd) { 133 outdata(fd, name, sb.sb_size); 134 } 135 if (f_verbose) { 136 print_entry(name, &sb); 137 } 138 } 139 140 write_eot(); 141 close_archive(); 142 return (0); 143 } 144 145 146 /* writetar - write a header block for a tar file 147 * 148 * DESCRIPTION 149 * 150 * Make a header block for the file name whose stat info is in st. 151 * Return header pointer for success, NULL if the name is too long. 152 * 153 * The tar header block is structured as follows: 154 * 155 * FIELD NAME OFFSET SIZE 156 * -------------|---------------|------ 157 * name 0 100 158 * mode 100 8 159 * uid 108 8 160 * gid 116 8 161 * size 124 12 162 * mtime 136 12 163 * chksum 148 8 164 * typeflag 156 1 165 * linkname 157 100 166 * magic 257 6 167 * version 263 2 168 * uname 265 32 169 * gname 297 32 170 * devmajor 329 8 171 * devminor 337 8 172 * prefix 345 155 173 * 174 * PARAMETERS 175 * 176 * char *name - name of file to create a header block for 177 * Stat *asb - pointer to the stat structure for the named file 178 * 179 */ 180 181 #ifdef __STDC__ 182 183 static void writetar(char *name, Stat *asb) 184 185 #else 186 187 static void writetar(name, asb) 188 char *name; 189 Stat *asb; 190 191 #endif 192 { 193 char *p; 194 char *prefix = (char *)NULL; 195 int i; 196 int sum; 197 char hdr[BLOCKSIZE]; 198 Link *from; 199 200 memset(hdr, 0, BLOCKSIZE); 201 if (strlen(name) > 255) { 202 warn(name, "name too long"); 203 return; 204 } 205 206 /* 207 * If the pathname is longer than TNAMLEN, but less than 255, then 208 * we can split it up into the prefix and the filename. 209 */ 210 if (strlen(name) > 100) { 211 prefix = name; 212 name += 155; 213 while (name > prefix && *name != '/') { 214 name--; 215 } 216 217 /* no slash found....hmmm.... */ 218 if (name == prefix) { 219 warn(prefix, "Name too long"); 220 return; 221 } 222 *name++ = '\0'; 223 } 224 225 #ifdef S_IFLNK 226 if ((asb->sb_mode & S_IFMT) == S_IFLNK) { 227 strcpy(&hdr[157], asb->sb_link); 228 asb->sb_size = 0; 229 } 230 #endif 231 strcpy(hdr, name); 232 sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT); 233 sprintf(&hdr[108], "%06o \0", asb->sb_uid); 234 sprintf(&hdr[116], "%06o \0", asb->sb_gid); 235 sprintf(&hdr[124], "%011lo ", (long) asb->sb_size); 236 sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime); 237 strncpy(&hdr[148], " ", 8); 238 hdr[156] = tartype(asb->sb_mode); 239 if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) { 240 strcpy(&hdr[157], from->l_name); 241 hdr[156] = LNKTYPE; 242 } 243 strcpy(&hdr[257], TMAGIC); 244 strncpy(&hdr[263], TVERSION, 2); 245 strcpy(&hdr[265], finduname((int) asb->sb_uid)); 246 strcpy(&hdr[297], findgname((int) asb->sb_gid)); 247 sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev)); 248 sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev)); 249 if (prefix != (char *)NULL) { 250 strncpy(&hdr[345], prefix, 155); 251 } 252 253 /* Calculate the checksum */ 254 255 sum = 0; 256 p = hdr; 257 for (i = 0; i < 500; i++) { 258 sum += 0xFF & *p++; 259 } 260 261 /* Fill in the checksum field. */ 262 263 sprintf(&hdr[148], "%06o \0", sum); 264 265 outwrite(hdr, BLOCKSIZE); 266 } 267 268 269 /* tartype - return tar file type from file mode 270 * 271 * DESCRIPTION 272 * 273 * tartype returns the character which represents the type of file 274 * indicated by "mode". 275 * 276 * PARAMETERS 277 * 278 * int mode - file mode from a stat block 279 * 280 * RETURNS 281 * 282 * The character which represents the particular file type in the 283 * ustar standard headers. 284 */ 285 286 #ifdef __STDC__ 287 288 static char tartype(int mode) 289 290 #else 291 292 static char tartype(mode) 293 int mode; 294 295 #endif 296 { 297 switch (mode & S_IFMT) { 298 299 #ifdef S_IFCTG 300 case S_IFCTG: 301 return(CONTTYPE); 302 #endif 303 304 case S_IFDIR: 305 return (DIRTYPE); 306 307 #ifdef S_IFLNK 308 case S_IFLNK: 309 return (SYMTYPE); 310 #endif 311 312 #ifdef S_IFFIFO 313 case S_IFIFO: 314 return (FIFOTYPE); 315 #endif 316 317 #ifdef S_IFCHR 318 case S_IFCHR: 319 return (CHRTYPE); 320 #endif 321 322 #ifdef S_IFBLK 323 case S_IFBLK: 324 return (BLKTYPE); 325 #endif 326 327 default: 328 return (REGTYPE); 329 } 330 } 331 332 333 /* writecpio - write a cpio archive header 334 * 335 * DESCRIPTION 336 * 337 * Writes a new CPIO style archive header for the file specified. 338 * 339 * PARAMETERS 340 * 341 * char *name - name of file to create a header block for 342 * Stat *asb - pointer to the stat structure for the named file 343 */ 344 345 #ifdef __STDC__ 346 347 static void writecpio(char *name, Stat *asb) 348 349 #else 350 351 static void writecpio(name, asb) 352 char *name; 353 Stat *asb; 354 355 #endif 356 { 357 uint namelen; 358 char header[M_STRLEN + H_STRLEN + 1]; 359 360 namelen = (uint) strlen(name) + 1; 361 strcpy(header, M_ASCII); 362 sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o", 363 USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 364 USH(asb->sb_uid), USH(asb->sb_gid)); 365 sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo", 366 #ifdef _POSIX_SOURCE 367 USH(asb->sb_nlink), USH(0), 368 #else 369 USH(asb->sb_nlink), USH(asb->sb_rdev), 370 #endif 371 f_mtime ? asb->sb_mtime : time((time_t *) 0), 372 namelen, asb->sb_size); 373 outwrite(header, M_STRLEN + H_STRLEN); 374 outwrite(name, namelen); 375 #ifdef S_IFLNK 376 if ((asb->sb_mode & S_IFMT) == S_IFLNK) { 377 outwrite(asb->sb_link, (uint) asb->sb_size); 378 } 379 #endif /* S_IFLNK */ 380 } 381