コード例 #1
0
ファイル: utils.c プロジェクト: jhbsz/OSI-OS
int setfile(struct stat *fs, int fd) {
	static struct timeval tv[2];
	struct stat ts;
	int rval, gotstat, islink, fdval;

	rval = 0;
	fdval = fd != -1;
	islink = !fdval && S_ISLNK(fs->st_mode);
	fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
	TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
	TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
	if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
		warn("%sutimes: %s", islink ? "l" : "", to.p_path);
		rval = 1;
	}
	if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
		gotstat = 0;
	else {
		gotstat = 1;
		ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
	}
	if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
		if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
chown(to.p_path, fs->st_uid, fs->st_gid))) {
			if (errno != EPERM) {
				warn("chown: %s", to.p_path);
				rval = 1;
			}
			fs->st_mode &= ~(S_ISUID | S_ISGID);
		}
	if (!gotstat || fs->st_mode != ts.st_mode)
		if (fdval ? fchmod(fd, fs->st_mode) : (islink ? lchmod(to.p_path, fs->st_mode) :
chmod(to.p_path, fs->st_mode))) {
			warn("chmod: %s", to.p_path);
			rval = 1;
		}
	if (!gotstat || fs->st_flags != ts.st_flags)
		if (fdval ? fchflags(fd, fs->st_flags) : (islink ? lchflags(to.p_path, fs->st_flags) :
chflags(to.p_path, fs->st_flags))) {
			warn("chflags: %s", to.p_path);
			rval = 1;
		}
	return (rval);
}
コード例 #2
0
ファイル: tape.c プロジェクト: Alkzndr/freebsd
int
extractfile(char *name)
{
	int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	int extsize;
	struct timeval mtimep[2], ctimep[2];
	struct entry *ep;
	char *buf;

	curfile.name = name;
	curfile.action = USING;
	mtimep[0].tv_sec = curfile.atime_sec;
	mtimep[0].tv_usec = curfile.atime_nsec / 1000;
	mtimep[1].tv_sec = curfile.mtime_sec;
	mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
	ctimep[0].tv_sec = curfile.atime_sec;
	ctimep[0].tv_usec = curfile.atime_nsec / 1000;
	ctimep[1].tv_sec = curfile.birthtime_sec;
	ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
	extsize = curfile.extsize;
	uid = getuid();
	if (uid == 0)
		uid = curfile.uid;
	gid = curfile.gid;
	mode = curfile.mode;
	flags = curfile.file_flags;
	switch (mode & IFMT) {

	default:
		fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
		skipfile();
		return (FAIL);

	case IFSOCK:
		vprintf(stdout, "skipped socket %s\n", name);
		skipfile();
		return (GOOD);

	case IFDIR:
		if (mflag) {
			ep = lookupname(name);
			if (ep == NULL || ep->e_flags & EXTRACT)
				panic("unextracted directory %s\n", name);
			skipfile();
			return (GOOD);
		}
		vprintf(stdout, "extract file %s\n", name);
		return (genliteraldir(name, curfile.ino));

	case IFLNK:
		lnkbuf[0] = '\0';
		pathlen = 0;
		buf = setupextattr(extsize);
		getfile(xtrlnkfile, xtrattr, xtrlnkskip);
		if (pathlen == 0) {
			vprintf(stdout,
			    "%s: zero length symbolic link (ignored)\n", name);
			return (GOOD);
		}
		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
			if (extsize > 0)
				set_extattr_link(name, buf, extsize);
			(void) lchown(name, uid, gid);
			(void) lchmod(name, mode);
			(void) lutimes(name, ctimep);
			(void) lutimes(name, mtimep);
			(void) lchflags(name, flags);
			return (GOOD);
		}
		return (FAIL);

	case IFIFO:
		vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mkfifo(name, 0600) < 0) {
			fprintf(stderr, "%s: cannot create fifo: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFCHR:
	case IFBLK:
		vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600,
		    (int)curfile.rdev) < 0) {
			fprintf(stderr, "%s: cannot create special file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFREG:
		vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0600)) < 0) {
			fprintf(stderr, "%s: cannot create file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		buf = setupextattr(extsize);
		getfile(xtrfile, xtrattr, xtrskip);
		if (extsize > 0)
			set_extattr_fd(ofile, name, buf, extsize);
		(void) fchown(ofile, uid, gid);
		(void) fchmod(ofile, mode);
		(void) futimes(ofile, ctimep);
		(void) futimes(ofile, mtimep);
		(void) fchflags(ofile, flags);
		(void) close(ofile);
		return (GOOD);
	}
	/* NOTREACHED */
}
コード例 #3
0
ファイル: fstest.c プロジェクト: VRciF/springy
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	struct utimbuf ut;
	long long flags;
	unsigned int i;
	char *endp;
	int rval;
	int more;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];

	more = 0;
	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL) {
					args[i].str = NULL;
					break;
				}
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK)
						== TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' && !isspace((unsigned char)*endp)) {
					fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags);
		}
		if (rval >= 0) {
			more = argv[i] && !strcmp(argv[i], ":");
			descriptor_add(rval);
		}
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, NUM(1));
		if (rval >= 0) {
			more = argv[i] && !strcmp(argv[i], ":");
			descriptor_add(rval);
		}
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), NUM(1));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), NUM(1));
		break;
	case ACTION_CHMOD:
		rval = chmod(STR(0), NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), NUM(1));
		break;
#endif
	case ACTION_CHOWN:
		rval = chown(STR(0), NUM(1), NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), NUM(1), NUM(2));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_UTIME :
		switch (i) {
		case 1 :
			rval = utime(STR(0), (struct utimbuf*)NULL);
			break;
		case 3:
			ut.actime = NUM(1);
			ut.modtime = NUM(2);
			rval = utime(STR(0), &ut);
			break;
		default :
			fprintf(stderr,"utime() requires 1 or 3 arguments\n");
			exit(1);
		}
		break;
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
#ifdef HAS_ACL
	case ACTION_GETFACL :
		rval = do_getfacl(STR(0), STR(1));
		if (rval == 0)
			return (i);
		break;
	case ACTION_SETFACL :
		rval = do_setfacl(STR(0), STR(1), STR(2));
		break;
#endif
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
		/* Do not output a "0" when more syscalls to come */
	if (!more)
		printf("0\n");
	return (i);
}
コード例 #4
0
ファイル: utils.c プロジェクト: nthery/DragonFlyBSD
int
setfile(struct stat *fs, int fd)
{
    static struct timeval tv[2];
    struct stat ts;
    int rval, gotstat, islink, fdval;

    rval = 0;
    fdval = fd != -1;
    islink = !fdval && S_ISLNK(fs->st_mode);
    fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
                   S_IRWXU | S_IRWXG | S_IRWXO;

    TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
    TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
    if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
        warn("%sutimes: %s", islink ? "l" : "", to.p_path);
        rval = 1;
    }
    if (fdval ? fstat(fd, &ts) :
            (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
        gotstat = 0;
    else {
        gotstat = 1;
        ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
                      S_IRWXU | S_IRWXG | S_IRWXO;
    }
    /*
     * Changing the ownership probably won't succeed, unless we're root
     * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
     * the mode; current BSD behavior is to remove all setuid bits on
     * chown.  If chown fails, lose setuid/setgid bits.
     */
    if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
        if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
                (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
                 chown(to.p_path, fs->st_uid, fs->st_gid))) {
            if (errno != EPERM) {
                warn("chown: %s", to.p_path);
                rval = 1;
            }
            fs->st_mode &= ~(S_ISUID | S_ISGID);
        }

    if (!gotstat || fs->st_mode != ts.st_mode)
        if (fdval ? fchmod(fd, fs->st_mode) :
                (islink ? lchmod(to.p_path, fs->st_mode) :
                 chmod(to.p_path, fs->st_mode))) {
            warn("chmod: %s", to.p_path);
            rval = 1;
        }

    if (!gotstat || fs->st_flags != ts.st_flags)
        if (fdval ?
                fchflags(fd, fs->st_flags) :
                (islink ? lchflags(to.p_path, fs->st_flags) :
                 chflags(to.p_path, fs->st_flags))) {
            warn("chflags: %s", to.p_path);
            rval = 1;
        }

    return (rval);
}
コード例 #5
0
ファイル: fstest.c プロジェクト: abhinavvv/skyefs
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];

	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL)
					break;
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if (scall->sd_args[i] & TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if (scall->sd_args[i] & TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' && !isspace((unsigned char)*endp)) {
					fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
					exit(1);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags);
		}
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), NUM(1));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), NUM(1));
		break;
	case ACTION_CHMOD:
		rval = chmod(STR(0), NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), NUM(1));
		break;
#endif
	case ACTION_CHOWN:
		rval = chown(STR(0), NUM(1), NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), NUM(1), NUM(2));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
    case ACTION_READDIR:
        rval = readdir_loop(STR(0));
        break;
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
	printf("0\n");
	return (i);
}
コード例 #6
0
ファイル: rm.c プロジェクト: hmatyschok/MeshBSD
static void
rm_file(char **argv)
{
    struct stat sb;
    int rval;
    char *f;

    /*
     * Remove a file.  POSIX 1003.2 states that, by default, attempting
     * to remove a directory is an error, so must always stat the file.
     */
    while ((f = *argv++) != NULL) {
        /* Assume if can't stat the file, can't unlink it. */
        if (lstat(f, &sb)) {
            if (Wflag) {
                sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
            } else {
                if (!fflag || errno != ENOENT) {
                    warn("%s", f);
                    eval = 1;
                }
                continue;
            }
        } else if (Wflag) {
            warnx("%s: %s", f, strerror(EEXIST));
            eval = 1;
            continue;
        }

        if (S_ISDIR(sb.st_mode) && !dflag) {
            warnx("%s: is a directory", f);
            eval = 1;
            continue;
        }
        if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
            continue;
        rval = 0;
        if (!uid && !S_ISWHT(sb.st_mode) &&
                (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
            rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
        if (rval == 0) {
            if (S_ISWHT(sb.st_mode))
                rval = undelete(f);
            else if (S_ISDIR(sb.st_mode))
                rval = rmdir(f);
            else {
                if (Pflag)
                    if (!rm_overwrite(f, &sb))
                        continue;
                rval = unlink(f);
            }
        }
        if (rval && (!fflag || errno != ENOENT)) {
            warn("%s", f);
            eval = 1;
        }
        if (vflag && rval == 0)
            (void)printf("%s\n", f);
        if (info && rval == 0) {
            info = 0;
            (void)printf("%s\n", f);
        }
    }
}
コード例 #7
0
ファイル: rm.c プロジェクト: hmatyschok/MeshBSD
static void
rm_tree(char **argv)
{
    FTS *fts;
    FTSENT *p;
    int needstat;
    int flags;
    int rval;

    /*
     * Remove a file hierarchy.  If forcing removal (-f), or interactive
     * (-i) or can't ask anyway (stdin_ok), don't stat the file.
     */
    needstat = !uid || (!fflag && !iflag && stdin_ok);

    /*
     * If the -i option is specified, the user can skip on the pre-order
     * visit.  The fts_number field flags skipped directories.
     */
#define	SKIPPED	1

    flags = FTS_PHYSICAL;
    if (!needstat)
        flags |= FTS_NOSTAT;
    if (Wflag)
        flags |= FTS_WHITEOUT;
    if (xflag)
        flags |= FTS_XDEV;
    if (!(fts = fts_open(argv, flags, NULL))) {
        if (fflag && errno == ENOENT)
            return;
        err(1, "fts_open");
    }
    while ((p = fts_read(fts)) != NULL) {
        switch (p->fts_info) {
        case FTS_DNR:
            if (!fflag || p->fts_errno != ENOENT) {
                warnx("%s: %s",
                      p->fts_path, strerror(p->fts_errno));
                eval = 1;
            }
            continue;
        case FTS_ERR:
            errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
        case FTS_NS:
            /*
             * Assume that since fts_read() couldn't stat the
             * file, it can't be unlinked.
             */
            if (!needstat)
                break;
            if (!fflag || p->fts_errno != ENOENT) {
                warnx("%s: %s",
                      p->fts_path, strerror(p->fts_errno));
                eval = 1;
            }
            continue;
        case FTS_D:
            /* Pre-order: give user chance to skip. */
            if (!fflag && !check(p->fts_path, p->fts_accpath,
                                 p->fts_statp)) {
                (void)fts_set(fts, p, FTS_SKIP);
                p->fts_number = SKIPPED;
            }
            else if (!uid &&
                     (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                     !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
                     lchflags(p->fts_accpath,
                              p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
                goto err;
            continue;
        case FTS_DP:
            /* Post-order: see if user skipped. */
            if (p->fts_number == SKIPPED)
                continue;
            break;
        default:
            if (!fflag &&
                    !check(p->fts_path, p->fts_accpath, p->fts_statp))
                continue;
        }

        rval = 0;
        if (!uid &&
                (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
            rval = lchflags(p->fts_accpath,
                            p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
        if (rval == 0) {
            /*
             * If we can't read or search the directory, may still be
             * able to remove it.  Don't print out the un{read,search}able
             * message unless the remove fails.
             */
            switch (p->fts_info) {
            case FTS_DP:
            case FTS_DNR:
                rval = rmdir(p->fts_accpath);
                if (rval == 0 || (fflag && errno == ENOENT)) {
                    if (rval == 0 && vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (rval == 0 && info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
                break;

            case FTS_W:
                rval = undelete(p->fts_accpath);
                if (rval == 0 && (fflag && errno == ENOENT)) {
                    if (vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
                break;

            case FTS_NS:
                /*
                 * Assume that since fts_read() couldn't stat
                 * the file, it can't be unlinked.
                 */
                if (fflag)
                    continue;
            /* FALLTHROUGH */

            case FTS_F:
            case FTS_NSOK:
                if (Pflag)
                    if (!rm_overwrite(p->fts_accpath, p->fts_info ==
                                      FTS_NSOK ? NULL : p->fts_statp))
                        continue;
            /* FALLTHROUGH */

            default:
                rval = unlink(p->fts_accpath);
                if (rval == 0 || (fflag && errno == ENOENT)) {
                    if (rval == 0 && vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (rval == 0 && info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
            }
        }
err:
        warn("%s", p->fts_path);
        eval = 1;
    }
    if (!fflag && errno)
        err(1, "fts_read");
    fts_close(fts);
}
コード例 #8
0
ファイル: verify.c プロジェクト: vocho/qnxpkgsrcmirror
static void
miss(NODE *p, char *tail)
{
	int create;
	char *tp;
	const char *type;
	u_int32_t flags;

	for (; p; p = p->next) {
		if (p->flags & F_OPT && !(p->flags & F_VISIT))
			continue;
		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
			continue;
		strcpy(tail, p->name);
		if (!(p->flags & F_VISIT))
			printf("missing: %s", path);
		switch (p->type) {
		case F_BLOCK:
		case F_CHAR:
			type = "device";
			break;
		case F_DIR:
			type = "directory";
			break;
		case F_LINK:
			type = "symlink";
			break;
		default:
			putchar('\n');
			continue;
		}

		create = 0;
		if (!(p->flags & F_VISIT) && uflag) {
			if (mtree_Wflag || p->type == F_LINK)
				goto createit;
			if (!(p->flags & (F_UID | F_UNAME)))
			    printf(
				" (%s not created: user not specified)", type);
			else if (!(p->flags & (F_GID | F_GNAME)))
			    printf(
				" (%s not created: group not specified)", type);
			else if (!(p->flags & F_MODE))
			    printf(
				" (%s not created: mode not specified)", type);
			else
 createit:
			switch (p->type) {
			case F_BLOCK:
			case F_CHAR:
				if (mtree_Wflag)
					continue;
				if (!(p->flags & F_DEV))
					printf(
				    " (%s not created: device not specified)",
					    type);
				else if (mknod(path,
				    p->st_mode | nodetoino(p->type),
				    p->st_rdev) == -1)
					printf(" (%s not created: %s)\n",
					    type, strerror(errno));
				else
					create = 1;
				break;
			case F_LINK:
				if (!(p->flags & F_SLINK))
					printf(
				    " (%s not created: link not specified)\n",
					    type);
				else if (symlink(p->slink, path))
					printf(
					    " (%s not created: %s)\n",
					    type, strerror(errno));
				else
					create = 1;
				break;
			case F_DIR:
				if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO))
					printf(" (not created: %s)",
					    strerror(errno));
				else
					create = 1;
				break;
			default:
				mtree_err("can't create create %s",
				    nodetype(p->type));
			}
		}
		if (create)
			printf(" (created)");
		if (p->type == F_DIR) {
			if (!(p->flags & F_VISIT))
				putchar('\n');
			for (tp = tail; *tp; ++tp)
				continue;
			*tp = '/';
			miss(p->child, tp + 1);
			*tp = '\0';
		} else
			putchar('\n');

		if (!create || mtree_Wflag)
			continue;
		if ((p->flags & (F_UID | F_UNAME)) &&
		    (p->flags & (F_GID | F_GNAME)) &&
		    (lchown(path, p->st_uid, p->st_gid))) {
			printf("%s: user/group/mode not modified: %s\n",
			    path, strerror(errno));
			printf("%s: warning: file mode %snot set\n", path,
			    (p->flags & F_FLAGS) ? "and file flags " : "");
			continue;
		}
		if (p->flags & F_MODE) {
			if (lchmod(path, p->st_mode))
				printf("%s: permissions not set: %s\n",
				    path, strerror(errno));
		}
#if HAVE_STRUCT_STAT_ST_FLAGS
		if ((p->flags & F_FLAGS) && p->st_flags) {
			if (iflag)
				flags = p->st_flags;
			else
				flags = p->st_flags & ~SP_FLGS;
			if (lchflags(path, flags))
				printf("%s: file flags not set: %s\n",
				    path, strerror(errno));
		}
#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
	}
}
コード例 #9
0
ファイル: pjdfstest.c プロジェクト: ChaosJohn/freebsd
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int name, rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];
#ifdef HAS_FREEBSD_ACL
	int entry_id = ACL_FIRST_ENTRY;
	acl_t acl, newacl;
	acl_entry_t entry, newentry;
#endif

	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL)
					break;
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' &&
				    !isspace((unsigned char)*endp)) {
					fprintf(stderr,
					    "invalid argument %u, number expected [%s]\n",
					    i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_OPENAT:
		flags = str2flags(open_flags, STR(2));
		if (flags & O_CREAT) {
			if (i == 3) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags,
			    (mode_t)NUM(3));
		} else {
			if (i == 4) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_UNLINKAT:
		rval = unlinkat(NUM(0), STR(1),
		    (int)str2flags(unlinkat_flags, STR(2)));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKDIRAT:
		rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_LINKAT:
		rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
		    (int)str2flags(linkat_flags, STR(4)));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_SYMLINKAT:
		rval = symlinkat(STR(0), NUM(1), STR(2));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_RENAMEAT:
		rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKFIFOAT:
		rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_BINDAT
	case ACTION_BINDAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CONNECT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_CONNECTAT
	case ACTION_CONNECTAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CHMOD:
		rval = chmod(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_FCHMOD:
		rval = fchmod(NUM(0), (mode_t)NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), (mode_t)NUM(1));
		break;
#endif
	case ACTION_FCHMODAT:
		rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
		    str2flags(fchmodat_flags, STR(3)));
		break;
	case ACTION_CHOWN:
		rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWN:
		rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWNAT:
		rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
		    (int)str2flags(fchownat_flags, STR(4)));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_FCHFLAGS
	case ACTION_FCHFLAGS:
		rval = fchflags(NUM(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_CHFLAGSAT
	case ACTION_CHFLAGSAT:
		rval = chflagsat(NUM(0), STR(1),
		    (unsigned long)str2flags(chflags_flags, STR(2)),
		    (int)str2flags(chflagsat_flags, STR(3)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTAT:
		rval = fstat64(NUM(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTATAT:
		rval = fstatat(NUM(0), STR(1), &sb,
		    (int)str2flags(fstatat_flags, STR(2)));
		if (rval == 0) {
			show_stats(&sb, STR(3));
			return (i);
		}
		break;
	case ACTION_PATHCONF:
	case ACTION_FPATHCONF:
	case ACTION_LPATHCONF:
	    {
		long lrval;

		name = str2name(pathconf_names, STR(1));
		if (name == -1) {
			fprintf(stderr, "unknown name %s", STR(1));
			exit(1);
		}
		errno = 0;
		switch (scall->sd_action) {
		case ACTION_PATHCONF:
			lrval = pathconf(STR(0), name);
			break;
		case ACTION_FPATHCONF:
			lrval = fpathconf(NUM(0), name);
			break;
		case ACTION_LPATHCONF:
			lrval = lpathconf(STR(0), name);
			break;
		default:
			abort();
		}
		if (lrval == -1 && errno == 0) {
			printf("unlimited\n");
			return (i);
		} else if (lrval >= 0) {
			printf("%ld\n", lrval);
			return (i);
		}
		rval = -1;
		break;
	    }
#ifdef HAS_FREEBSD_ACL
	case ACTION_PREPENDACL:
		rval = -1;

		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			break;

		newacl = acl_from_text(STR(1));
		if (acl == NULL)
			break;

		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
			entry_id = ACL_NEXT_ENTRY;

			if (acl_create_entry_np(&acl, &entry, 0))
				break;

			if (acl_copy_entry(entry, newentry))
				break;
		}

		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
		break;
	case ACTION_READACL:
		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			rval = -1;
		else
			rval = 0;
		break;
#endif
	case ACTION_WRITE:
		rval = write(NUM(0), STR(1), strlen(STR(1)));
		break;
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
	printf("0\n");
	return (i);
}
コード例 #10
0
ファイル: libMacFUSE.c プロジェクト: GaloisInc/SPADE
static int
spade_fsetattr_x(const char *path, struct setattr_x *attr,
        struct fuse_file_info *fi) {
    int res;
    uid_t uid = -1;
    gid_t gid = -1;

    if (SETATTR_WANTS_MODE(attr)) {
        res = lchmod(path, attr->mode);
        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_UID(attr)) {
        uid = attr->uid;
    }

    if (SETATTR_WANTS_GID(attr)) {
        gid = attr->gid;
    }

    if ((uid != -1) || (gid != -1)) {
        res = lchown(path, uid, gid);
        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_SIZE(attr)) {
        if (fi) {
            res = ftruncate(fi->fh, attr->size);
        } else {
            res = truncate(path, attr->size);
        }
        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_MODTIME(attr)) {
        struct timeval tv[2];
        if (!SETATTR_WANTS_ACCTIME(attr)) {
            gettimeofday(&tv[0], NULL);
        } else {
            tv[0].tv_sec = attr->acctime.tv_sec;
            tv[0].tv_usec = attr->acctime.tv_nsec / 1000;
        }
        tv[1].tv_sec = attr->modtime.tv_sec;
        tv[1].tv_usec = attr->modtime.tv_nsec / 1000;
        res = utimes(path, tv);
        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_CRTIME(attr)) {
        struct attrlist attributes;

        attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
        attributes.reserved = 0;
        attributes.commonattr = ATTR_CMN_CRTIME;
        attributes.dirattr = 0;
        attributes.fileattr = 0;
        attributes.forkattr = 0;
        attributes.volattr = 0;

        res = setattrlist(path, &attributes, &attr->crtime,
                sizeof (struct timespec), FSOPT_NOFOLLOW);

        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_CHGTIME(attr)) {
        struct attrlist attributes;

        attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
        attributes.reserved = 0;
        attributes.commonattr = ATTR_CMN_CHGTIME;
        attributes.dirattr = 0;
        attributes.fileattr = 0;
        attributes.forkattr = 0;
        attributes.volattr = 0;

        res = setattrlist(path, &attributes, &attr->chgtime,
                sizeof (struct timespec), FSOPT_NOFOLLOW);

        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_BKUPTIME(attr)) {
        struct attrlist attributes;

        attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
        attributes.reserved = 0;
        attributes.commonattr = ATTR_CMN_BKUPTIME;
        attributes.dirattr = 0;
        attributes.fileattr = 0;
        attributes.forkattr = 0;
        attributes.volattr = 0;

        res = setattrlist(path, &attributes, &attr->bkuptime,
                sizeof (struct timespec), FSOPT_NOFOLLOW);

        if (res == -1) {
            return -errno;
        }
    }

    if (SETATTR_WANTS_FLAGS(attr)) {
        res = lchflags(path, attr->flags);
        if (res == -1) {
            return -errno;
        }
    }

    return 0;
}