157110Smuller /*- 257110Smuller * Copyright (c) 1992 Keith Muller. 357110Smuller * Copyright (c) 1992 The Regents of the University of California. 457110Smuller * All rights reserved. 557110Smuller * 657110Smuller * This code is derived from software contributed to Berkeley by 757110Smuller * Keith Muller of the University of California, San Diego. 857110Smuller * 957110Smuller * %sccs.include.redist.c% 1057110Smuller */ 1157110Smuller 1257110Smuller #ifndef lint 13*57539Smuller static char sccsid[] = "@(#)file_subs.c 1.2 (Berkeley) 01/14/93"; 1457110Smuller #endif /* not lint */ 1557110Smuller 1657110Smuller #include <sys/types.h> 1757110Smuller #include <sys/time.h> 1857110Smuller #include <sys/stat.h> 1957110Smuller #include <unistd.h> 2057110Smuller #include <sys/param.h> 2157110Smuller #include <fcntl.h> 2257110Smuller #include <string.h> 2357110Smuller #include <stdio.h> 2457110Smuller #include <ctype.h> 2557110Smuller #include <errno.h> 2657110Smuller #include <sys/uio.h> 2757110Smuller #include <stdlib.h> 2857110Smuller #include "pax.h" 2957110Smuller #include "extern.h" 3057110Smuller 3157110Smuller static int 3257110Smuller mk_link __P((register char *,register struct stat *,register char *, int)); 3357110Smuller 3457110Smuller /* 3557110Smuller * routines that deal with file operations such as: creating, removing; 3657110Smuller * and setting access modes, uid/gid and times of files 3757110Smuller */ 3857110Smuller 3957110Smuller #define FILEBITS (S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) 4057110Smuller #define SETBITS (S_ISUID | S_ISGID) 4157110Smuller #define ABITS (FILEBITS | SETBITS) 4257110Smuller 4357110Smuller /* 4457110Smuller * file_creat() 4557110Smuller * Create and open a file. 4657110Smuller * Return: 4757110Smuller * file descriptor or -1 for failure 4857110Smuller */ 4957110Smuller 5057110Smuller #if __STDC__ 5157110Smuller int 5257110Smuller file_creat(register ARCHD *arcn) 5357110Smuller #else 5457110Smuller int 5557110Smuller file_creat(arcn) 5657110Smuller register ARCHD *arcn; 5757110Smuller #endif 5857110Smuller { 5957110Smuller int fd = -1; 6057110Smuller mode_t file_mode; 6157110Smuller int oerrno; 6257110Smuller 6357110Smuller /* 6457110Smuller * assume file doesn't exist, so just try to create it, most times this 6557110Smuller * works. We have to take special handling when the file does exist. To 6657110Smuller * detect this, we use O_EXCL. For example when trying to create a 6757110Smuller * file and a character device or fifo exists with the same name, we 6857110Smuller * can accidently open the device by mistake (or block waiting to open) 6957110Smuller * If we find that the open has failed, then figure spend the effore to 7057110Smuller * figure out why. This strategy was found to have better average 7157110Smuller * performance in common use than checking the file (and the path) 7257110Smuller * first with lstat. 7357110Smuller */ 7457110Smuller file_mode = arcn->sb.st_mode & FILEBITS; 7557110Smuller if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 7657110Smuller file_mode)) >= 0) 7757110Smuller return(fd); 7857110Smuller 7957110Smuller /* 8057110Smuller * the file seems to exist. First we try to get rid of it (found to be 8157110Smuller * the second most common failure when traced). If this fails, only 8257110Smuller * then we go to the expense to check and create the path to the file 8357110Smuller */ 8457110Smuller if (unlnk_exist(arcn->name, arcn->type) != 0) 8557110Smuller return(-1); 8657110Smuller 8757110Smuller for (;;) { 8857110Smuller /* 8957110Smuller * try to open it again, if this fails, check all the nodes in 9057110Smuller * the path and give it a final try. if chk_path() finds that 9157110Smuller * it cannot fix anything, we will skip the last attempt 9257110Smuller */ 9357110Smuller if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC, 9457110Smuller file_mode)) >= 0) 9557110Smuller break; 9657110Smuller oerrno = errno; 9757110Smuller if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) { 9857110Smuller syswarn(1, oerrno, "Unable to create %s", arcn->name); 9957110Smuller return(-1); 10057110Smuller } 10157110Smuller } 10257110Smuller return(fd); 10357110Smuller } 10457110Smuller 10557110Smuller /* 10657110Smuller * file_close() 10757110Smuller * Close file descriptor to a file just created by pax. Sets modes, 10857110Smuller * ownership and times as required. 10957110Smuller * Return: 11057110Smuller * 0 for success, -1 for failure 11157110Smuller */ 11257110Smuller 11357110Smuller #if __STDC__ 11457110Smuller void 11557110Smuller file_close(register ARCHD *arcn, int fd) 11657110Smuller #else 11757110Smuller void 11857110Smuller file_close(arcn, fd) 11957110Smuller register ARCHD *arcn; 12057110Smuller int fd; 12157110Smuller #endif 12257110Smuller { 12357110Smuller int res = 0; 12457110Smuller 12557110Smuller if (fd < 0) 12657110Smuller return; 12757110Smuller if (close(fd) < 0) 12857110Smuller syswarn(0, errno, "Unable to close file descriptor on %s", 12957110Smuller arcn->name); 13057110Smuller 13157110Smuller /* 13257110Smuller * set owner/groups first as this may strip off mode bits we want 13357110Smuller * then set file permission modes. Then set file access and 13457110Smuller * modification times. 13557110Smuller */ 13657110Smuller if (pids) 13757110Smuller res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid); 13857110Smuller 13957110Smuller /* 14057110Smuller * IMPORTANT SECURITY NOTE: 141*57539Smuller * if not preserving mode or we cannot set uid/gid, then PROHIBIT 14257110Smuller * set uid/gid bits 14357110Smuller */ 14457110Smuller if (!pmode || res) 14557110Smuller arcn->sb.st_mode &= ~(SETBITS); 14657110Smuller if (pmode) 14757110Smuller set_pmode(arcn->name, arcn->sb.st_mode); 14857110Smuller if (patime || pmtime) 14957110Smuller set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0); 15057110Smuller } 15157110Smuller 15257110Smuller /* 15357110Smuller * lnk_creat() 15457110Smuller * Create a hard link to arcn->ln_name from arcn->name. arcn->ln_name 15557110Smuller * must exist; 15657110Smuller * Return: 15757110Smuller * 0 if ok, -1 otherwise 15857110Smuller */ 15957110Smuller 16057110Smuller #if __STDC__ 16157110Smuller int 16257110Smuller lnk_creat(register ARCHD *arcn) 16357110Smuller #else 16457110Smuller int 16557110Smuller lnk_creat(arcn) 16657110Smuller register ARCHD *arcn; 16757110Smuller #endif 16857110Smuller { 16957110Smuller struct stat sb; 17057110Smuller 17157110Smuller /* 17257110Smuller * we may be running as root, so we have to be sure that link target 17357110Smuller * is not a directory, so we lstat and check 17457110Smuller */ 17557110Smuller if (lstat(arcn->ln_name, &sb) < 0) { 17657110Smuller syswarn(1,errno,"Unable to link to %s from %s", arcn->ln_name, 17757110Smuller arcn->name); 17857110Smuller return(-1); 17957110Smuller } 18057110Smuller 18157110Smuller if (S_ISDIR(sb.st_mode)) { 182*57539Smuller warn(1, "A hard link to the directory %s is not allowed", 18357110Smuller arcn->ln_name); 18457110Smuller return(-1); 18557110Smuller } 18657110Smuller 18757110Smuller return(mk_link(arcn->ln_name, &sb, arcn->name, 0)); 18857110Smuller } 18957110Smuller 19057110Smuller /* 19157110Smuller * cross_lnk() 19257110Smuller * Create a hard link to arcn->org_name from arcn->name. Only used in copy 19357110Smuller * with the -l flag. No warning or error if this does not succeed (we will 19457110Smuller * then just create the file) 19557110Smuller * Return: 19657110Smuller * 1 if copy() should try to create this file node 19757110Smuller * 0 if cross_lnk() ok, -1 for fatal flaw (like linking to self). 19857110Smuller */ 19957110Smuller 20057110Smuller #if __STDC__ 20157110Smuller int 20257110Smuller cross_lnk(register ARCHD *arcn) 20357110Smuller #else 20457110Smuller int 20557110Smuller cross_lnk(arcn) 20657110Smuller register ARCHD *arcn; 20757110Smuller #endif 20857110Smuller { 20957110Smuller /* 21057110Smuller * try to make a link to orginal file (-l flag in copy mode). make sure 21157110Smuller * we do not try to link to directories in case we are running as root 21257110Smuller * (and it might succeed). 21357110Smuller */ 21457110Smuller if (arcn->type == PAX_DIR) 21557110Smuller return(1); 21657110Smuller return(mk_link(arcn->org_name, &(arcn->sb), arcn->name, 1)); 21757110Smuller } 21857110Smuller 21957110Smuller /* 22057110Smuller * chk_same() 221*57539Smuller * In copy mode if we are not trying to make hard links between the src 22257110Smuller * and destinations, make sure we are not going to overwrite ourselves by 22357110Smuller * accident. This slows things down a little, but we have to protect all 22457110Smuller * those people who make typing errors. 22557110Smuller * Return: 22657110Smuller * 1 the target does not exist, go ahead and copy 22757110Smuller * 0 skip it file exists (-k) or may be the same as source file 22857110Smuller */ 22957110Smuller 23057110Smuller #if __STDC__ 23157110Smuller int 23257110Smuller chk_same(register ARCHD *arcn) 23357110Smuller #else 23457110Smuller int 23557110Smuller chk_same(arcn) 23657110Smuller register ARCHD *arcn; 23757110Smuller #endif 23857110Smuller { 23957110Smuller struct stat sb; 24057110Smuller 24157110Smuller /* 24257110Smuller * if file does not exist, return. if file exists and -k, skip it 24357110Smuller * quietly 24457110Smuller */ 24557110Smuller if (lstat(arcn->name, &sb) < 0) 24657110Smuller return(1); 24757110Smuller if (kflag) 24857110Smuller return(0); 24957110Smuller 25057110Smuller /* 25157110Smuller * better make sure the user does not have src == dest by mistake 25257110Smuller */ 25357110Smuller if ((arcn->sb.st_dev == sb.st_dev) && (arcn->sb.st_ino == sb.st_ino)) { 25457110Smuller warn(1, "Unable to copy %s, file would overwrite itself", 25557110Smuller arcn->name); 25657110Smuller return(0); 25757110Smuller } 25857110Smuller return(1); 25957110Smuller } 26057110Smuller 26157110Smuller /* 26257110Smuller * mk_link() 26357110Smuller * try to make a hard link between two files. if ign set, we do not 26457110Smuller * complain. 26557110Smuller * Return: 26657110Smuller * 0 if successful (or we are done with this file but no error, such as 26757110Smuller * finding the from file exists and the user has set -k). 268*57539Smuller * 1 when ign was set to indicates we could not make the link but we 269*57539Smuller * should try to copy/extract the file as that might work (and is an 270*57539Smuller * allowed option). -1 an error occurred. 27157110Smuller */ 27257110Smuller 27357110Smuller #if __STDC__ 27457110Smuller static int 27557110Smuller mk_link(register char *to, register struct stat *to_sb, register char *from, 27657110Smuller int ign) 27757110Smuller #else 27857110Smuller static int 27957110Smuller mk_link(to, to_sb, from, ign) 28057110Smuller register char *to; 28157110Smuller register struct stat *to_sb; 28257110Smuller register char *from; 28357110Smuller int ign; 28457110Smuller #endif 28557110Smuller { 28657110Smuller struct stat sb; 28757110Smuller int oerrno; 28857110Smuller 28957110Smuller /* 29057110Smuller * if from file exists, it has to be unlinked to make the link. If the 29157110Smuller * file exists and -k is set, skip it quietly 29257110Smuller */ 29357110Smuller if (lstat(from, &sb) == 0) { 29457110Smuller if (kflag) 29557110Smuller return(0); 29657110Smuller 29757110Smuller /* 29857110Smuller * make sure it is not the same file, protect the user 29957110Smuller */ 30057110Smuller if ((to_sb->st_dev==sb.st_dev)&&(to_sb->st_ino == sb.st_ino)) { 30157110Smuller warn(1, "Unable to link file %s to itself", to); 30257110Smuller return(-1);; 30357110Smuller } 30457110Smuller 30557110Smuller /* 30657110Smuller * try to get rid of the file, based on the type 30757110Smuller */ 30857110Smuller if (S_ISDIR(sb.st_mode)) { 30957110Smuller if (rmdir(from) < 0) { 31057110Smuller syswarn(1, errno, "Unable to remove %s", from); 31157110Smuller return(-1); 31257110Smuller } 31357110Smuller } else if (unlink(from) < 0) { 31457110Smuller if (!ign) { 31557110Smuller syswarn(1, errno, "Unable to remove %s", from); 31657110Smuller return(-1); 31757110Smuller } 31857110Smuller return(1); 31957110Smuller } 32057110Smuller } 32157110Smuller 32257110Smuller /* 32357110Smuller * from file is gone (or did not exist), try to make the hard link. 32457110Smuller * if it fails, check the path and try it again (if chk_path() says to 32557110Smuller * try again) 32657110Smuller */ 32757110Smuller for (;;) { 32857110Smuller if (link(to, from) == 0) 32957110Smuller break; 33057110Smuller oerrno = errno; 33157110Smuller if (chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0) 33257110Smuller continue; 33357110Smuller if (!ign) { 33457110Smuller syswarn(1, oerrno, "Could not link to %s from %s", to, 33557110Smuller from); 33657110Smuller return(-1); 33757110Smuller } 33857110Smuller return(1); 33957110Smuller } 34057110Smuller 34157110Smuller /* 34257110Smuller * all right the link was made 34357110Smuller */ 34457110Smuller return(0); 34557110Smuller } 34657110Smuller 34757110Smuller /* 34857110Smuller * node_creat() 34957110Smuller * create an entry in the file system (other than a file or hard link). 35057110Smuller * If successful, sets uid/gid modes and times as required. 35157110Smuller * Return: 35257110Smuller * 0 if ok, -1 otherwise 35357110Smuller */ 35457110Smuller 35557110Smuller #if __STDC__ 35657110Smuller int 35757110Smuller node_creat(register ARCHD *arcn) 35857110Smuller #else 35957110Smuller int 36057110Smuller node_creat(arcn) 36157110Smuller register ARCHD *arcn; 36257110Smuller #endif 36357110Smuller { 36457110Smuller register int res; 36557110Smuller register int ign = 0; 36657110Smuller register int oerrno; 36757110Smuller register int pass = 0; 36857110Smuller mode_t file_mode; 36957110Smuller struct stat sb; 37057110Smuller 37157110Smuller /* 37257110Smuller * create node based on type, if that fails try to unlink the node and 37357110Smuller * try again. finally check the path and try again. As noted in the 37457110Smuller * file and link creation routines, this method seems to exhibit the 37557110Smuller * best performance in general use workloads. 37657110Smuller */ 37757110Smuller file_mode = arcn->sb.st_mode & FILEBITS; 37857110Smuller 37957110Smuller for (;;) { 38057110Smuller switch(arcn->type) { 38157110Smuller case PAX_DIR: 38257110Smuller res = mkdir(arcn->name, file_mode); 38357110Smuller if (ign) 38457110Smuller res = 0; 38557110Smuller break; 38657110Smuller case PAX_CHR: 38757110Smuller file_mode |= S_IFCHR; 38857110Smuller res = mknod(arcn->name, file_mode, arcn->sb.st_rdev); 38957110Smuller break; 39057110Smuller case PAX_BLK: 39157110Smuller file_mode |= S_IFBLK; 39257110Smuller res = mknod(arcn->name, file_mode, arcn->sb.st_rdev); 39357110Smuller break; 39457110Smuller case PAX_FIF: 39557110Smuller res = mkfifo(arcn->name, file_mode); 39657110Smuller break; 39757110Smuller case PAX_SCK: 39857110Smuller /* 39957110Smuller * Skip sockets, operation has no meaning under BSD 40057110Smuller */ 401*57539Smuller warn(0, 402*57539Smuller "%s skipped. Sockets cannot be copied or extracted", 40357110Smuller arcn->name); 40457110Smuller return(-1); 40557110Smuller case PAX_SLK: 40657110Smuller if ((res = symlink(arcn->ln_name, arcn->name)) == 0) 40757110Smuller return(0); 40857110Smuller break; 40957110Smuller case PAX_CTG: 41057110Smuller case PAX_HLK: 41157110Smuller case PAX_HRG: 41257110Smuller case PAX_REG: 413*57539Smuller default: 41457110Smuller /* 415*57539Smuller * we should never get here 41657110Smuller */ 417*57539Smuller warn(0, "%s has an unknown file type, skipping", 418*57539Smuller arcn->name); 41957110Smuller return(-1); 42057110Smuller } 42157110Smuller 42257110Smuller /* 42357110Smuller * if we were able to create the node break out of the loop, 42457110Smuller * otherwise try to unlink the node and try again. if that 42557110Smuller * fails check the full path and try a final time. 42657110Smuller */ 42757110Smuller if (res == 0) 42857110Smuller break; 42957110Smuller 43057110Smuller /* 43157110Smuller * we failed to make the node 43257110Smuller */ 43357110Smuller oerrno = errno; 43457110Smuller if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0) 43557110Smuller return(-1); 43657110Smuller 43757110Smuller if (++pass <= 1) 43857110Smuller continue; 43957110Smuller 44057110Smuller if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) { 44157110Smuller syswarn(1, oerrno, "Could not create: %s", arcn->name); 44257110Smuller return(-1); 44357110Smuller } 44457110Smuller } 44557110Smuller 44657110Smuller /* 44757110Smuller * we were able to create the node. set uid/gid, modes and times 44857110Smuller */ 44957110Smuller if (pids) 45057110Smuller res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid); 45157110Smuller else 45257110Smuller res = 0; 45357110Smuller 45457110Smuller /* 45557110Smuller * IMPORTANT SECURITY NOTE: 456*57539Smuller * if not preserving mode or we cannot set uid/gid, then PROHIBIT any 45757110Smuller * set uid/gid bits 45857110Smuller */ 45957110Smuller if (!pmode || res) 46057110Smuller arcn->sb.st_mode &= ~(SETBITS); 46157110Smuller if (pmode) 46257110Smuller set_pmode(arcn->name, arcn->sb.st_mode); 46357110Smuller 46457110Smuller if (arcn->type == PAX_DIR) { 46557110Smuller /* 46657110Smuller * Dirs must be processed again at end of extract to set times 46757110Smuller * and modes to agree with those stored in the archive. However 46857110Smuller * to allow extract to continue, we may have to also set owner 46957110Smuller * rights. This allows nodes in the archive that are children 47057110Smuller * of this directory to be extracted without failure. Both time 47157110Smuller * and modes will be fixed after the entire archive is read and 47257110Smuller * before pax exits. 47357110Smuller */ 47457110Smuller if (access(arcn->name, R_OK | W_OK | X_OK) < 0) { 47557110Smuller if (lstat(arcn->name, &sb) < 0) { 47657110Smuller syswarn(0, errno,"Could not access %s (stat)", 47757110Smuller arcn->name); 47857110Smuller set_pmode(arcn->name,file_mode | S_IRWXU); 47957110Smuller } else { 48057110Smuller /* 48157110Smuller * We have to add rights to the dir, so we make 48257110Smuller * sure to restore the mode. The mode must be 48357110Smuller * restored AS CREATED and not as stored if 48457110Smuller * pmode is not set. 48557110Smuller */ 48657110Smuller set_pmode(arcn->name, 48757110Smuller ((sb.st_mode & FILEBITS) | S_IRWXU)); 48857110Smuller if (!pmode) 48957110Smuller arcn->sb.st_mode = sb.st_mode; 49057110Smuller } 49157110Smuller 49257110Smuller /* 49357110Smuller * we have to force the mode to what was set here, 49457110Smuller * since we changed it from the default as created. 49557110Smuller */ 49657110Smuller add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1); 49757110Smuller } else if (pmode || patime || pmtime) 49857110Smuller add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0); 49957110Smuller } 50057110Smuller 50157110Smuller if (patime || pmtime) 50257110Smuller set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0); 50357110Smuller return(0); 50457110Smuller } 50557110Smuller 50657110Smuller /* 50757110Smuller * unlnk_exist() 50857110Smuller * Remove node from file system with the specified name. We pass the type 50957110Smuller * of the node that is going to replace it. When we try to create a 51057110Smuller * directory and find that it already exists, we allow processing to 51157110Smuller * continue as proper modes etc will always be set for it later on. 51257110Smuller * Return: 51357110Smuller * 0 is ok to proceed, no file with the specified name exists 51457110Smuller * -1 we were unable to remove the node, or we should not remove it (-k) 51557110Smuller * 1 we found a directory and we were going to create a directory. 51657110Smuller */ 51757110Smuller 51857110Smuller #if __STDC__ 51957110Smuller int 52057110Smuller unlnk_exist(register char *name, register int type) 52157110Smuller #else 52257110Smuller int 52357110Smuller unlnk_exist(name, type) 52457110Smuller register char *name; 52557110Smuller register int type; 52657110Smuller #endif 52757110Smuller { 52857110Smuller struct stat sb; 52957110Smuller 53057110Smuller /* 53157110Smuller * the file does not exist, or -k we are done 53257110Smuller */ 53357110Smuller if (lstat(name, &sb) < 0) 53457110Smuller return(0); 53557110Smuller if (kflag) 53657110Smuller return(-1); 53757110Smuller 53857110Smuller if (S_ISDIR(sb.st_mode)) { 53957110Smuller /* 54057110Smuller * try to remove a directory, if it fails and we were going to 54157110Smuller * create a directory anyway, tell the caller (return a 1) 54257110Smuller */ 54357110Smuller if (rmdir(name) < 0) { 54457110Smuller if (type == PAX_DIR) 54557110Smuller return(1); 54657110Smuller syswarn(1,errno,"Unable to remove directory %s", name); 54757110Smuller return(-1); 54857110Smuller } 54957110Smuller return(0); 55057110Smuller } 55157110Smuller 55257110Smuller /* 55357110Smuller * try to get rid of all non-directory type nodes 55457110Smuller */ 55557110Smuller if (unlink(name) < 0) { 55657110Smuller syswarn(1, errno, "Could not unlink %s", name); 55757110Smuller return(-1); 55857110Smuller } 55957110Smuller return(0); 56057110Smuller } 56157110Smuller 56257110Smuller /* 56357110Smuller * chk_path() 56457110Smuller * We were trying to create some kind of node in the file system and it 56557110Smuller * failed. chk_path() makes sure the path up to the node exists and is 56657110Smuller * writeable. When we have to create a directory that is missing along the 56757110Smuller * path somewhere, the directory we create will be set to the same 56857110Smuller * uid/gid as the file has (when uid and gid are being preserved). 56957110Smuller * NOTE: this routine is a real performance loss. It is only used as a 57057110Smuller * last resort when trying to create entries in the file system. 57157110Smuller * Return: 57257110Smuller * -1 when it could find nothing it is allowed to fix. 57357110Smuller * 0 otherwise 57457110Smuller */ 57557110Smuller 57657110Smuller #if __STDC__ 57757110Smuller int 57857110Smuller chk_path( register char *name, uid_t st_uid, gid_t st_gid) 57957110Smuller #else 58057110Smuller int 58157110Smuller chk_path(name, st_uid, st_gid) 58257110Smuller register char *name; 58357110Smuller uid_t st_uid; 58457110Smuller gid_t st_gid; 58557110Smuller #endif 58657110Smuller { 58757110Smuller register char *spt = name; 58857110Smuller struct stat sb; 58957110Smuller int retval = -1; 59057110Smuller 59157110Smuller /* 59257110Smuller * watch out for paths with nodes stored directly in / (e.g. /bozo) 59357110Smuller */ 59457110Smuller if (*spt == '/') 59557110Smuller ++spt; 59657110Smuller 59757110Smuller for(;;) { 59857110Smuller /* 59957110Smuller * work foward from the first / and check each part of the path 60057110Smuller */ 60157110Smuller spt = strchr(spt, '/'); 60257110Smuller if (spt == NULL) 60357110Smuller break; 60457110Smuller *spt = '\0'; 60557110Smuller 60657110Smuller /* 60757110Smuller * if it exists we assume it is a directory, it is not within 608*57539Smuller * the spec (at least it seems to read that way) to alter the 60957110Smuller * file system for nodes NOT EXPLICITLY stored on the archive. 61057110Smuller * If that assumption is changed, you would test the node here 61157110Smuller * and figure out how to get rid of it (probably like some 612*57539Smuller * recursive unlink()) or fix up the directory permissions if 613*57539Smuller * required (do an access()). 61457110Smuller */ 61557110Smuller if (lstat(name, &sb) == 0) { 61657110Smuller *(spt++) = '/'; 61757110Smuller continue; 61857110Smuller } 61957110Smuller 62057110Smuller /* 62157110Smuller * the path fails at this point, see if we can create the 62257110Smuller * needed directory and continue on 62357110Smuller */ 62457110Smuller if (mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) { 62557110Smuller *spt = '/'; 62657110Smuller retval = -1; 62757110Smuller break; 62857110Smuller } 62957110Smuller 63057110Smuller /* 63157110Smuller * we were able to create the directory. We will tell the 63257110Smuller * caller that we found something to fix, and it is ok to try 63357110Smuller * and create the node again. 63457110Smuller */ 63557110Smuller retval = 0; 63657110Smuller if (pids) 63757110Smuller (void)set_ids(name, st_uid, st_gid); 63857110Smuller 63957110Smuller /* 64057110Smuller * make sure the user doen't have some strange umask that 64157110Smuller * causes this newly created directory to be unusable. We fix 64257110Smuller * the modes and restore them back to the creation default at 64357110Smuller * the end of pax 64457110Smuller */ 64557110Smuller if ((access(name, R_OK | W_OK | X_OK) < 0) && 64657110Smuller (lstat(name, &sb) == 0)) { 64757110Smuller set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU)); 64857110Smuller add_dir(name, spt - name, &sb, 1); 64957110Smuller } 65057110Smuller *(spt++) = '/'; 65157110Smuller continue; 65257110Smuller } 65357110Smuller return(retval); 65457110Smuller } 65557110Smuller 65657110Smuller /* 65757110Smuller * set_ftime() 65857110Smuller * Set the access time and modification time for a named file. If frc is 65957110Smuller * non-zero we force these times to be set even if the the user did not 66057110Smuller * request access and/or modification time preservation (this is also 66157110Smuller * used by -t to reset access times). 66257110Smuller * When ign is zero, only those times the user has asked for are set, the 66357110Smuller * other ones are left alone. We do not assume the un-documented feature 66457110Smuller * of many utimes() implementations that consider a 0 time value as a do 66557110Smuller * not set request. 66657110Smuller */ 66757110Smuller 66857110Smuller #if __STDC__ 66957110Smuller void 67057110Smuller set_ftime(char *fnm, time_t mtime, time_t atime, int frc) 67157110Smuller #else 67257110Smuller void 67357110Smuller set_ftime(fnm, mtime, atime, frc) 67457110Smuller char *fnm; 67557110Smuller time_t mtime; 67657110Smuller time_t atime; 67757110Smuller int frc; 67857110Smuller #endif 67957110Smuller { 68057110Smuller static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}}; 68157110Smuller struct stat sb; 68257110Smuller 68357110Smuller tv[0].tv_sec = (long)atime; 68457110Smuller tv[1].tv_sec = (long)mtime; 68557110Smuller if (!frc && (!patime || !pmtime)) { 68657110Smuller /* 68757110Smuller * if we are not forcing, only set those times the user wants 68857110Smuller * set. We get the current values of the times if we need them. 68957110Smuller */ 69057110Smuller if (lstat(fnm, &sb) == 0) { 69157110Smuller if (!patime) 69257110Smuller tv[0].tv_sec = (long)sb.st_atime; 69357110Smuller if (!pmtime) 69457110Smuller tv[1].tv_sec = (long)sb.st_mtime; 69557110Smuller } else 69657110Smuller syswarn(0,errno,"Unable to obtain file stats %s", fnm); 69757110Smuller } 69857110Smuller 69957110Smuller /* 70057110Smuller * set the times 70157110Smuller */ 70257110Smuller if (utimes(fnm, tv) < 0) 70357110Smuller syswarn(1, errno, "Access/modification time set failed on: %s", 70457110Smuller fnm); 70557110Smuller return; 70657110Smuller } 70757110Smuller 70857110Smuller /* 70957110Smuller * set_ids() 71057110Smuller * set the uid and gid of a file system node 71157110Smuller * Return: 71257110Smuller * 0 when set, -1 on failure 71357110Smuller */ 71457110Smuller 71557110Smuller #if __STDC__ 71657110Smuller int 71757110Smuller set_ids(char *fnm, uid_t uid, gid_t gid) 71857110Smuller #else 71957110Smuller int 72057110Smuller set_ids(fnm, uid, gid) 72157110Smuller char *fnm; 72257110Smuller uid_t uid; 72357110Smuller gid_t gid; 72457110Smuller #endif 72557110Smuller { 72657110Smuller if (chown(fnm, uid, gid) < 0) { 72757110Smuller syswarn(1, errno, "Unable to set file uid/gid of %s", fnm); 72857110Smuller return(-1); 72957110Smuller } 73057110Smuller return(0); 73157110Smuller } 73257110Smuller 73357110Smuller /* 73457110Smuller * set_pmode() 73557110Smuller * Set file access mode 73657110Smuller */ 73757110Smuller 73857110Smuller #if __STDC__ 73957110Smuller void 74057110Smuller set_pmode(char *fnm, mode_t mode) 74157110Smuller #else 74257110Smuller void 74357110Smuller set_pmode(fnm, mode) 74457110Smuller char *fnm; 74557110Smuller mode_t mode; 74657110Smuller #endif 74757110Smuller { 74857110Smuller mode &= ABITS; 74957110Smuller if (chmod(fnm, mode) < 0) 75057110Smuller syswarn(1, errno, "Could not set permissions on %s", fnm); 75157110Smuller return; 75257110Smuller } 75357110Smuller 75457110Smuller /* 75557110Smuller * file_write() 75657110Smuller * Write/copy a file (during copy or archive extract). This routine knows 75757110Smuller * how to copy files with lseek holes in it. (Which are read as file 75857110Smuller * blocks containing all 0's but do not have any file blocks associated 75957110Smuller * with the data). Typical examples of these are files created by dbm 76057110Smuller * variants (.pag files). While the file size of these files are huge, the 76157110Smuller * actual storage is quite small (the files are sparse). The problem is 76257110Smuller * the holes read as all zeros so are probably stored on the archive that 76357110Smuller * way (there is no way to determine if the file block is really a hole, 76457110Smuller * we only know that a file block of all zero's can be a hole). 76557110Smuller * At this writing, no major archive format knows how to archive files 76657110Smuller * with holes. However, on extraction (or during copy, -rw) we have to 76757110Smuller * deal with these files. Without detecting the holes, the files can 76857110Smuller * consume a lot of file space if just written to disk. This replacement 76957110Smuller * for write when passed the basic allocation size of a file system block, 77057110Smuller * uses lseek whenever it detects the input data is all 0 within that 77157110Smuller * file block. In more detail, the strategy is as follows: 77257110Smuller * While the input is all zero keep doing an lseek. Keep track of when we 77357110Smuller * pass over file block boundries. Only write when we hit a non zero 77457110Smuller * input. once we have written a file block, we continue to write it to 77557110Smuller * the end (we stop looking at the input). When we reach the start of the 77657110Smuller * next file block, start checking for zero blocks again. Working on file 77757110Smuller * block boundries significantly reduces the overhead when copying files 77857110Smuller * that are NOT very sparse. This overhead (when compared to a write) is 77957110Smuller * almost below the measurement resolution on many systems. Without it, 78057110Smuller * files with holes cannot be safely copied. It does has a side effect as 78157110Smuller * it can put holes into files that did not have them before, but that is 78257110Smuller * not a problem since the file contents are unchanged (in fact it saves 78357110Smuller * file space). (Except on paging files for diskless clients. But since we 78457110Smuller * cannot determine one of those file from here, we ignore them). If this 78557110Smuller * ever ends up on a system where CTG files are supported and the holes 78657110Smuller * are not desired, just do a conditional test in those routines that 78757110Smuller * call file_write() and have it call write() instead. BEFORE CLOSING THE 78857110Smuller * FILE, make sure to call file_flush() when the last write finishes with 78957110Smuller * an empty block. A lot of file systems will not create an lseek hole at 79057110Smuller * the end. In this case we drop a single 0 at the end to force the 79157110Smuller * trailing 0's in the file. 79257110Smuller * ---Parameters--- 79357110Smuller * rem: how many bytes left in this file system block 79457110Smuller * isempt: have we written to the file block yet (is it empty) 79557110Smuller * sz: basic file block allocation size 79657110Smuller * cnt: number of bytes on this write 79757110Smuller * str: buffer to write 79857110Smuller * Return: 79957110Smuller * number of bytes written, -1 on write (or lseek) error. 80057110Smuller */ 80157110Smuller 80257110Smuller #if __STDC__ 80357110Smuller int 80457110Smuller file_write(int fd, char *str, register int cnt, int *rem, int *isempt, int sz, 80557110Smuller char *name) 80657110Smuller #else 80757110Smuller int 80857110Smuller file_write(fd, str, cnt, rem, isempt, sz, name) 80957110Smuller int fd; 81057110Smuller char *str; 81157110Smuller register int cnt; 81257110Smuller int *rem; 81357110Smuller int *isempt; 81457110Smuller int sz; 81557110Smuller char *name; 81657110Smuller #endif 81757110Smuller { 81857110Smuller register char *pt; 81957110Smuller register char *end; 82057110Smuller register int wcnt; 82157110Smuller register char *st = str; 82257110Smuller 82357110Smuller /* 82457110Smuller * while we have data to process 82557110Smuller */ 82657110Smuller while (cnt) { 82757110Smuller if (!*rem) { 82857110Smuller /* 82957110Smuller * We are now at the start of file system block again 83057110Smuller * (or what we think one is...). start looking for 83157110Smuller * empty blocks again 83257110Smuller */ 83357110Smuller *isempt = 1; 83457110Smuller *rem = sz; 83557110Smuller } 83657110Smuller 83757110Smuller /* 83857110Smuller * only examine up to the end of the current file block or 83957110Smuller * remaining characters to write, whatever is smaller 84057110Smuller */ 84157110Smuller wcnt = MIN(cnt, *rem); 84257110Smuller cnt -= wcnt; 84357110Smuller *rem -= wcnt; 84457110Smuller if (*isempt) { 84557110Smuller /* 84657110Smuller * have not written to this block yet, so we keep 84757110Smuller * looking for zero's 84857110Smuller */ 84957110Smuller pt = st; 85057110Smuller end = st + wcnt; 85157110Smuller 85257110Smuller /* 85357110Smuller * look for a zero filled buffer 85457110Smuller */ 85557110Smuller while ((pt < end) && (*pt == '\0')) 85657110Smuller ++pt; 85757110Smuller 85857110Smuller if (pt == end) { 85957110Smuller /* 86057110Smuller * skip, buf is empty so far 86157110Smuller */ 86257110Smuller if (lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) { 86357110Smuller syswarn(1,errno,"File seek on %s", 86457110Smuller name); 86557110Smuller return(-1); 86657110Smuller } 86757110Smuller st = pt; 86857110Smuller continue; 86957110Smuller } 87057110Smuller /* 87157110Smuller * drat, the buf is not zero filled 87257110Smuller */ 87357110Smuller *isempt = 0; 87457110Smuller } 87557110Smuller 87657110Smuller /* 87757110Smuller * have non-zero data in this file system block, have to write 87857110Smuller */ 87957110Smuller if (write(fd, st, wcnt) != wcnt) { 88057110Smuller syswarn(1, errno, "Failed write to file %s", name); 88157110Smuller return(-1); 88257110Smuller } 88357110Smuller st += wcnt; 88457110Smuller } 88557110Smuller return(st - str); 88657110Smuller } 88757110Smuller 88857110Smuller /* 88957110Smuller * file_flush() 89057110Smuller * when the last file block in a file is zero, many file systems will not 89157110Smuller * let us create a hole at the end. To get the last block with zeros, we 89257110Smuller * write the last BYTE with a zero (back up one byte and write a zero). 89357110Smuller */ 89457110Smuller 89557110Smuller #if __STDC__ 89657110Smuller void 89757110Smuller file_flush(int fd, char *fname, int isempt) 89857110Smuller #else 89957110Smuller void 90057110Smuller file_flush(fd, fname, isempt) 90157110Smuller int fd; 90257110Smuller char *fname; 90357110Smuller int isempt; 90457110Smuller #endif 90557110Smuller { 90657110Smuller static char blnk[] = "\0"; 90757110Smuller 90857110Smuller /* 90957110Smuller * silly test, but make sure we are only called when the last block is 91057110Smuller * filled with all zeros. 91157110Smuller */ 91257110Smuller if (!isempt) 91357110Smuller return; 91457110Smuller 91557110Smuller /* 91657110Smuller * move back one byte and write a zero 91757110Smuller */ 91857110Smuller if (lseek(fd, (off_t)-1, SEEK_CUR) < 0) { 91957110Smuller syswarn(1, errno, "Failed seek on file %s", fname); 92057110Smuller return; 92157110Smuller } 92257110Smuller 92357110Smuller if (write(fd, blnk, 1) < 0) 92457110Smuller syswarn(1, errno, "Failed write to file %s", fname); 92557110Smuller return; 92657110Smuller } 92757110Smuller 92857110Smuller /* 92957110Smuller * rdfile_close() 93057110Smuller * close a file we have beed reading (to copy or archive). If we have to 93157110Smuller * reset access time (tflag) do so (the times are stored in arcn). 93257110Smuller */ 93357110Smuller 93457110Smuller #if __STDC__ 93557110Smuller void 93657110Smuller rdfile_close(register ARCHD *arcn, register int *fd) 93757110Smuller #else 93857110Smuller void 93957110Smuller rdfile_close(arcn, fd) 94057110Smuller register ARCHD *arcn; 94157110Smuller register int *fd; 94257110Smuller #endif 94357110Smuller { 94457110Smuller /* 94557110Smuller * make sure the file is open 94657110Smuller */ 94757110Smuller if (*fd < 0) 94857110Smuller return; 94957110Smuller 95057110Smuller (void)close(*fd); 95157110Smuller *fd = -1; 95257110Smuller if (!tflag) 95357110Smuller return; 95457110Smuller 95557110Smuller /* 95657110Smuller * user wants last access time reset 95757110Smuller */ 95857110Smuller set_ftime(arcn->org_name, arcn->sb.st_mtime, arcn->sb.st_atime, 1); 95957110Smuller return; 96057110Smuller } 96157110Smuller 96257110Smuller /* 96357110Smuller * set_crc() 96457110Smuller * read a file to calculate its crc. This is a real drag. Archive formats 96557110Smuller * that have this, end up reading the file twice (we have to write the 96657110Smuller * header WITH the crc before writing the file contents. Oh well... 96757110Smuller * Return: 96857110Smuller * 0 if was able to calculate the crc, -1 otherwise 96957110Smuller */ 97057110Smuller 97157110Smuller #if __STDC__ 97257110Smuller int 97357110Smuller set_crc(register ARCHD *arcn, register int fd) 97457110Smuller #else 97557110Smuller int 97657110Smuller set_crc(arcn, fd) 97757110Smuller register ARCHD *arcn; 97857110Smuller register int fd; 97957110Smuller #endif 98057110Smuller { 98157110Smuller register int i; 98257110Smuller register int res; 98357110Smuller off_t cpcnt = 0L; 98457110Smuller u_long size; 98557110Smuller unsigned long crc = 0L; 98657110Smuller char tbuf[FILEBLK]; 98757110Smuller struct stat sb; 98857110Smuller 98957110Smuller if (fd < 0) { 99057110Smuller /* 99157110Smuller * hmm, no fd, should never happen. well no crc then. 99257110Smuller */ 99357110Smuller arcn->crc = 0L; 99457110Smuller return(0); 99557110Smuller } 99657110Smuller 99757110Smuller if ((size = (u_long)arcn->sb.st_blksize) > (u_long)sizeof(tbuf)) 99857110Smuller size = (u_long)sizeof(tbuf); 99957110Smuller 100057110Smuller /* 100157110Smuller * read all the bytes we think that there are in the file. If the user 100257110Smuller * is trying to archive an active file, forget this file. 100357110Smuller */ 100457110Smuller for(;;) { 100557110Smuller if ((res = read(fd, tbuf, size)) <= 0) 100657110Smuller break; 100757110Smuller cpcnt += res; 100857110Smuller for (i = 0; i < res; ++i) 100957110Smuller crc += (tbuf[i] & 0xff); 101057110Smuller } 101157110Smuller 101257110Smuller /* 101357110Smuller * safety check. we want to avoid archiving files that are active as 101457110Smuller * they can create inconsistant archive copies. 101557110Smuller */ 101657110Smuller if (cpcnt != arcn->sb.st_size) 101757110Smuller warn(1, "File changed size %s", arcn->org_name); 101857110Smuller else if (fstat(fd, &sb) < 0) 101957110Smuller syswarn(1, errno, "Failed stat on %s", arcn->org_name); 102057110Smuller else if (arcn->sb.st_mtime != sb.st_mtime) 102157110Smuller warn(1, "File %s was modified during read", arcn->org_name); 102257110Smuller else if (lseek(fd, (off_t)0L, SEEK_SET) < 0) 102357110Smuller syswarn(1, errno, "File rewind failed on: %s", arcn->org_name); 102457110Smuller else { 102557110Smuller arcn->crc = crc; 102657110Smuller return(0); 102757110Smuller } 102857110Smuller return(-1); 102957110Smuller } 1030