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