Beispiel #1
0
void sys_stat_check_functions()
{
    (void)chmod((const char *)1234, (mode_t)0);
    (void)fchmod(0, (mode_t)0);
#if HAVE_XXXAT
    (void)fchmodat(0, (const char *)1234, (mode_t)0, 0);
#endif
    (void)fstat(0, (struct stat *)1234);
#if HAVE_XXXAT
    (void)fstatat(0, (const char *)1234, (struct stat *)1234, 0);
#endif
    (void)futimens(0, (const struct timespec *)1234);
    (void)lstat((const char *)1234, (struct stat *)1234);
    (void)mkdir((const char *)1234, (mode_t)0);
#if HAVE_XXXAT
    (void)mkdirat(0, (const char *)1234, (mode_t)0);
#endif
    (void)mkfifo((const char *)1234, (mode_t)0);
    (void)mkfifoat(0, (const char *)1234, (mode_t)0);
    (void)mknod((const char *)1234, (mode_t)0, (dev_t)0);
    (void)mknodat(0, (const char *)1234, (mode_t)0, (dev_t)0);
    (void)stat((const char *)1234, (struct stat *)1234);
    (void)umask((mode_t)0);
    (void)utimensat(0, (const char *)1234, (const struct timespec *)1234, 0);
}
Beispiel #2
0
CAMLprim value netsys_mkfifoat(value dirfd, value path, value mode)
{
#ifdef HAVE_AT
    if (mkfifoat(Int_val(dirfd), String_val(path), Int_val(mode)) == -1)
	uerror("mkfifoat", path);
    return Val_unit;
#else
    invalid_argument("Netsys_posix.mkfifoat not available");
#endif
}
Beispiel #3
0
int
ast_mkfifoat(int cwd, const char* path, mode_t mode)
{
	int	r = -1;

	PATHIFY(cwd, path, 1, 1);
	RESTART(r, mkfifoat(cwd, path, mode));
	PATHEND();

	return r;
}
Beispiel #4
0
static int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, const char *to) {
        int r;

        assert(from);
        assert(st);
        assert(to);

        r = mkfifoat(dt, to, st->st_mode & 07777);
        if (r < 0)
                return -errno;

        if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
                r = -errno;

        if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
                r = -errno;

        return r;
}
Beispiel #5
0
/*
 * Given a file descriptor, create a capability with specific rights and
 * make sure only those rights work. 
*/
static int
try_file_ops(int filefd, int dirfd, cap_rights_t rights)
{
	struct stat sb;
	struct statfs sf;
	cap_rights_t erights;
	int fd_cap, fd_capcap, dfd_cap;
	ssize_t ssize, ssize2;
	off_t off;
	void *p;
	char ch;
	int ret, is_nfs;
	struct pollfd pollfd;
	int success = -1;

	REQUIRE(fstatfs(filefd, &sf));
	is_nfs = (strcmp("nfs", sf.f_fstypename) == 0);

	REQUIRE(fd_cap = cap_new(filefd, rights));
	CHECK(cap_getrights(fd_cap, &erights) == 0);
	CHECK(rights == erights);
	REQUIRE(fd_capcap = cap_new(fd_cap, rights));
	CHECK(cap_getrights(fd_capcap, &erights) == 0);
	CHECK(rights == erights);
	CHECK(fd_capcap != fd_cap);
	REQUIRE(dfd_cap = cap_new(dirfd, rights));
	CHECK(cap_getrights(dfd_cap, &erights) == 0);
	CHECK(rights == erights);

	ssize = read(fd_cap, &ch, sizeof(ch));
	CHECK_RESULT(read, CAP_READ, ssize >= 0);

	ssize = write(fd_cap, &ch, sizeof(ch));
	CHECK_RESULT(write, CAP_WRITE, ssize >= 0);

	off = lseek(fd_cap, 0, SEEK_SET);
	CHECK_RESULT(lseek, CAP_SEEK, off >= 0);

	ssize = pread(fd_cap, &ch, sizeof(ch), 0);
	ssize2 = pread(fd_cap, &ch, sizeof(ch), 0);
	CHECK_RESULT(pread, CAP_PREAD, ssize >= 0);
	CHECK(ssize == ssize2);

	ssize = pwrite(fd_cap, &ch, sizeof(ch), 0);
	CHECK_RESULT(pwrite, CAP_PWRITE, ssize >= 0);

	p = mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP);

	p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_R);

	p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_W);

	p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_X);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_RW);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_RX);

	p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_WX);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
	    MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP_RWX);

	ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600);
	CHECK_RESULT(openat(O_CREATE | O_RDONLY),
	    CAP_CREATE | CAP_READ | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
	ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND,
	    0600);
	CHECK_RESULT(openat(O_CREATE | O_WRONLY | O_APPEND),
	    CAP_CREATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
	ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600);
	CHECK_RESULT(openat(O_CREATE | O_RDWR | O_APPEND),
	    CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);

	ret = fsync(fd_cap);
	CHECK_RESULT(fsync, CAP_FSYNC, ret == 0);

	ret = openat(dirfd, "cap_fsync", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY);
	CHECK_RESULT(openat(O_FSYNC | O_RDONLY),
	    CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND);
	CHECK_RESULT(openat(O_FSYNC | O_WRONLY | O_APPEND),
	    CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND);
	CHECK_RESULT(openat(O_FSYNC | O_RDWR | O_APPEND),
	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY);
	CHECK_RESULT(openat(O_SYNC | O_RDONLY),
	    CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND);
	CHECK_RESULT(openat(O_SYNC | O_WRONLY | O_APPEND),
	    CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND);
	CHECK_RESULT(openat(O_SYNC | O_RDWR | O_APPEND),
	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0);

	ret = ftruncate(fd_cap, 0);
	CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0);

	ret = openat(dirfd, "cap_ftruncate", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY);
	CHECK_RESULT(openat(O_TRUNC | O_RDONLY),
	    CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY);
	CHECK_RESULT(openat(O_TRUNC | O_WRONLY),
	    CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR);
	CHECK_RESULT(openat(O_TRUNC | O_RDWR),
	    CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(unlinkat(dirfd, "cap_ftruncate", 0) == 0);

	ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600);
	CHECK_RESULT(openat(O_CREATE | O_WRONLY),
	    CAP_CREATE | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
	ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600);
	CHECK_RESULT(openat(O_CREATE | O_RDWR),
	    CAP_CREATE | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP,
	    ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);

	ret = openat(dirfd, "cap_fsync", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY);
	CHECK_RESULT(openat(O_FSYNC | O_WRONLY),
	    CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR);
	CHECK_RESULT(openat(O_FSYNC | O_RDWR),
	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY);
	CHECK_RESULT(openat(O_SYNC | O_WRONLY),
	    CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR);
	CHECK_RESULT(openat(O_SYNC | O_RDWR),
	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);
	CHECK(ret == -1 || close(ret) == 0);
	CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0);

	/*
	 * Note: this is not expected to work over NFS.
	 */
	ret = fchflags(fd_cap, UF_NODUMP);
	CHECK_RESULT(fchflags, CAP_FCHFLAGS,
	    ret == 0 || (is_nfs && errno == EOPNOTSUPP));

	ret = openat(dirfd, "cap_chflagsat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0);
	CHECK_RESULT(chflagsat, CAP_CHFLAGSAT | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_chflagsat", 0) == 0);

	ret = fchown(fd_cap, -1, -1);
	CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0);

	ret = openat(dirfd, "cap_fchownat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0);
	CHECK_RESULT(fchownat, CAP_FCHOWN | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_fchownat", 0) == 0);

	ret = fchmod(fd_cap, 0644);
	CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0);

	ret = openat(dirfd, "cap_fchmodat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0);
	CHECK_RESULT(fchmodat, CAP_FCHMOD | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_fchmodat", 0) == 0);

	ret = fcntl(fd_cap, F_GETFL);
	CHECK_RESULT(fcntl(F_GETFL), CAP_FCNTL, ret >= 0);
	ret = fcntl(fd_cap, F_SETFL, ret);
	CHECK_RESULT(fcntl(F_SETFL), CAP_FCNTL, ret == 0);

	/* XXX flock */

	ret = fstat(fd_cap, &sb);
	CHECK_RESULT(fstat, CAP_FSTAT, ret == 0);

	ret = openat(dirfd, "cap_fstatat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = fstatat(dfd_cap, "cap_fstatat", &sb, 0);
	CHECK_RESULT(fstatat, CAP_FSTAT | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_fstatat", 0) == 0);

	ret = fstatfs(fd_cap, &sf);
	CHECK_RESULT(fstatfs, CAP_FSTATFS, ret == 0);

	ret = fpathconf(fd_cap, _PC_NAME_MAX);
	CHECK_RESULT(fpathconf, CAP_FPATHCONF, ret >= 0);

	ret = futimes(fd_cap, NULL);
	CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0);

	ret = openat(dirfd, "cap_futimesat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = futimesat(dfd_cap, "cap_futimesat", NULL);
	CHECK_RESULT(futimesat, CAP_FUTIMES | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_futimesat", 0) == 0);

	ret = openat(dirfd, "cap_linkat_src", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0);
	CHECK_RESULT(linkat, CAP_LINKAT | CAP_LOOKUP, ret == 0);
	CHECK(unlinkat(dirfd, "cap_linkat_src", 0) == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_linkat_dst", 0) == 0);

	ret = mkdirat(dfd_cap, "cap_mkdirat", 0700);
	CHECK_RESULT(mkdirat, CAP_MKDIRAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR) == 0);

	ret = mkfifoat(dfd_cap, "cap_mkfifoat", 0600);
	CHECK_RESULT(mkfifoat, CAP_MKFIFOAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_mkfifoat", 0) == 0);

	ret = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0);
	CHECK_RESULT(mknodat, CAP_MKNODAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_mknodat", 0) == 0);

	/* TODO: renameat(2) */

	ret = symlinkat("test", dfd_cap, "cap_symlinkat");
	CHECK_RESULT(symlinkat, CAP_SYMLINKAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == -1 || unlinkat(dirfd, "cap_symlinkat", 0) == 0);

	ret = openat(dirfd, "cap_unlinkat", O_CREAT, 0600);
	CHECK(ret >= 0);
	CHECK(close(ret) == 0);
	ret = unlinkat(dfd_cap, "cap_unlinkat", 0);
	CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", 0) == 0);
	ret = mkdirat(dirfd, "cap_unlinkat", 0700);
	CHECK(ret == 0);
	ret = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR);
	CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);
	CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR) == 0);

	pollfd.fd = fd_cap;
	pollfd.events = POLLIN | POLLERR | POLLHUP;
	pollfd.revents = 0;

	ret = poll(&pollfd, 1, 0);
	if (rights & CAP_EVENT)
		CHECK((pollfd.revents & POLLNVAL) == 0);
	else
		CHECK((pollfd.revents & POLLNVAL) != 0);

	/* XXX: select, kqueue */

	close(fd_cap);
	close(fd_capcap);

	if (success == -1) {
		fprintf(stderr, "No tests for rights 0x%jx.\n",
		    (uintmax_t)rights);
		success = FAILED;
	}
	return (success);
}
Beispiel #6
0
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);
}
Beispiel #7
0
int
main (int argc, char **argv)
{
  struct ev_loop *loop;
  struct timeval  tv[2];

  char  dirname[10];
  char *shmdata;
  int   rundir, rundirs[NUM_PROCS], sharedir;
  int   pagesize;
  int   i, j;

  // use the default event loop unless you have special needs
  loop = ev_default_loop (EVBACKEND_EPOLL); //EVFLAG_AUTO);
 
  rundir   = get_rundir();
  pagesize = getpagesize();
  
  // Prepare shared data directory
  if ((mkdirat(rundir, SHARE_DIR_NAME, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
    fprintf(stderr, "could not make share directory: %s\n", strerror(errno));
    return -1;
  }
  if ((sharedir = openat(rundir, SHARE_DIR_NAME, O_DIRECTORY)) < 0) {
    fprintf(stderr, "could not open share directory: %s\n", strerror(errno));
    return -1;
  }

  // Prepare worker rundirs
  for (i=0; i<NUM_PROCS; ++i) {
    sprintf(dirname, "%d", i);
    if ((mkdirat(rundir, dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
      fprintf(stderr, "worker %d: could not make runtime directory: %s\n", i, strerror(errno));
      return -1;
    }
    if ((rundirs[i] = openat(rundir, dirname, O_DIRECTORY)) < 0) {
      fprintf(stderr, "worker %d: could not open runtime directory: %s\n", i, strerror(errno));
      return -1;
    }

    if ((mkfifoat(rundirs[i], "inputfile", S_IRUSR | S_IWUSR)) != 0) {
      fprintf(stderr, "%s: could not create FIFO: %s\n", "inputfile", strerror(errno));
    }
  }

  // Memory map some data;
  for (j=0; j<NUM_SHMS; ++j) {
    // Maybe just use ids for shared SHM names
    shms[j] = openat(sharedir, "dbfile", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    ftruncate(shms[j], pagesize);
    shmdata = mmap((caddr_t)0, pagesize, PROT_WRITE, MAP_SHARED, shms[j], 0);
    strcpy(shmdata, "Very important DB data.");
    
    // Now "share" it
    for (i=0; i<NUM_PROCS; ++i) {
      linkat(sharedir, "dbfile", rundirs[i], "dbfile", 0);
    }
  }

  //ev_set_timeout_collect_interval (loop, 0.0001);
  //ev_set_io_collect_interval (loop, 0.0001);

  // Start children
  for (i=0; i<NUM_PROCS; ++i) {
    pid_t pid = fork();
    if (pid == 0) {
      // Child
      fchdir(rundirs[i]);
      if (execle(argv[1], gnu_basename(argv[1]), "outputfile", "dbfile", "inputfile", NULL, NULL)) {
	fputs("Could not exec: ", stderr);
	fputs(strerror(errno), stderr);
	fputc('\n', stderr);
	exit(EXIT_FAILURE);
      }
    }
    else if (pid > 0) {
      // Parent
    }
  }

  // Initialize watchers
  for (i=0; i<NUM_PROCS; ++i) {
    ev_io *wio = &input_watcher[i];

    fifos[i] = openat(rundirs[i], "inputfile", O_WRONLY);
    wio->data = (void*)i;
    ev_io_init(wio, input_cb, fifos[i], EV_WRITE);
    ev_io_start(loop, wio);
  }
  
  ev_child *wchld = &child_watcher;
  ev_child_init(wchld, child_cb, 0, 1);
  ev_child_start(loop, wchld);

  // now wait for events to arrive
  gettimeofday(tv+0, NULL);
  ev_loop (loop, 0);
  gettimeofday(tv+1, NULL);
  
  // unloop was called, so exit
  long t = (tv[1].tv_sec - tv[0].tv_sec) * 1000000
           + (tv[1].tv_usec - tv[0].tv_usec);

  printf("\nTime taken: %lfs (%lfms average)\n\n",
      ((double)t) / 1000000.0,
      ((double)t) * NUM_PROCS / NUM_JOBS);

  // Hang up
  /*
  puts("Closing pipes...");
  for (i=0; i<NUM_PROCS; ++i) {
    close(fifos[i]);
  }
  */

  puts("Waiting for children processes to terminate...");
  pid_t pid;
  do {
    pid = wait(NULL);
    if(pid == -1 && errno != ECHILD) {
      perror("Error during wait()");
      abort();
    }
  } while (pid > 0);

  // Cleanup shms
  puts("Cleaning SHMs...");
  for (j=0; j<NUM_SHMS; ++j) {
    ftruncate(shms[j], 0);
    close(shms[i]);
  }

  // Finally...
  puts("Done.");
  return 0;
}