/* * Given a file descriptor, create a capability with specific rights and * make sure only those rights work. */ static int try_file_ops(int fd, cap_rights_t rights) { struct stat sb; struct statfs sf; int fd_cap, fd_capcap; ssize_t ssize, ssize2; off_t off; void *p; char ch; int ret, is_nfs; struct pollfd pollfd; int success = PASSED; REQUIRE(fstatfs(fd, &sf)); is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename)) == 0); REQUIRE(fd_cap = cap_new(fd, rights)); REQUIRE(fd_capcap = cap_new(fd_cap, rights)); CHECK(fd_capcap != fd_cap); pollfd.fd = fd_cap; pollfd.events = POLLIN | POLLERR | POLLHUP; pollfd.revents = 0; ssize = read(fd_cap, &ch, sizeof(ch)); CHECK_RESULT(read, CAP_READ | CAP_SEEK, ssize >= 0); ssize = pread(fd_cap, &ch, sizeof(ch), 0); ssize2 = pread(fd_cap, &ch, sizeof(ch), 0); CHECK_RESULT(pread, CAP_READ, ssize >= 0); CHECK(ssize == ssize2); ssize = write(fd_cap, &ch, sizeof(ch)); CHECK_RESULT(write, CAP_WRITE | CAP_SEEK, ssize >= 0); ssize = pwrite(fd_cap, &ch, sizeof(ch), 0); CHECK_RESULT(pwrite, CAP_WRITE, ssize >= 0); off = lseek(fd_cap, 0, SEEK_SET); CHECK_RESULT(lseek, CAP_SEEK, off >= 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 = fstat(fd_cap, &sb); CHECK_RESULT(fstat, CAP_FSTAT, ret == 0); p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ); p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_WRITE); p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC); p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE); p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_MAPEXEC); p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC | CAP_WRITE); p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd_cap, 0); CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE | CAP_MAPEXEC); ret = fsync(fd_cap); CHECK_RESULT(fsync, CAP_FSYNC, ret == 0); ret = fchown(fd_cap, -1, -1); CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0); ret = fchmod(fd_cap, 0644); CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0); /* XXX flock */ ret = ftruncate(fd_cap, 0); CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 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 = poll(&pollfd, 1, 0); if (rights & CAP_POLL_EVENT) CHECK((pollfd.revents & POLLNVAL) == 0); else CHECK((pollfd.revents & POLLNVAL) != 0); /* XXX: select, kqueue */ close (fd_cap); return (success); }
void setterm(char *type) { register int unknown; char ltcbuf[TCBUFSIZE]; if (type[0] == 0) type = "xx"; unknown = 0; putpad(TE); if (tgetent(ltcbuf, type) != 1) { unknown++; lcpy(ltcbuf, "xx|dumb:", sizeof ltcbuf); } gettmode(); /* must call gettmode() before setsize(). GR */ setsize(); aoftspace = tspace; zap(); /* * Initialize keypad arrow keys. */ addmac1(KU, "k", "up", arrows, 1); addmac1(KD, "j", "down", arrows, 1); addmac1(KL, "h", "left", arrows, 1); addmac1(KR, "l", "right", arrows, 1); addmac1(KH, "H", "home", arrows, 1); /* * Handle funny termcap capabilities */ if (xCS && SC && RC) { if (AL==NULL) AL=""; if (DL==NULL) DL=""; } if (AL_PARM && AL==NULL) AL=""; if (DL_PARM && DL==NULL) DL=""; if (IC && IM==NULL) IM=""; if (IC && EI==NULL) EI=""; if (!GT) BT=NULL; /* If we can't tab, we can't backtab either */ #ifdef TIOCLGET #define HAS_JOB_CONTROL #endif #ifdef _SC_JOB_CONTROL #define HAS_JOB_CONTROL #endif #ifdef HAS_JOB_CONTROL /* * Now map users susp char to ^Z, being careful that the susp * overrides any arrow key, but only for hackers (=new tty driver). */ { static char sc[2]; int i /* , fnd */; if (sysconf(_SC_JOB_CONTROL) != -1) { /* * If a system supports job control but no job * control shell is used, only one method of * detection remains: Our session id equals our * process group id. Any job control shell would * have created at least one new process group. * But as the VSUSP key may be active, we have * to override arrow keys either. */ #ifndef _CRAY /* getsid() is a bad syscall on UNICOS */ if (getsid(0) != getpgid(0)) #endif /* !_CRAY */ ldisc = 2; /* value of NTTYDISC */ sc[0] = tty.c_cc[VSUSP]; sc[1] = 0; if (tty.c_cc[VSUSP] == CTRL('z')) { for (i=0; i<=4; i++) if (arrows[i].cap && arrows[i].cap[0] == CTRL('z')) addmac(sc, NULL, NULL, arrows); } else if (sc[0] #ifdef _PC_VDISABLE && sc[0] != fpathconf(1, _PC_VDISABLE) #endif ) addmac(sc, "\32", "susp", arrows); } } #endif /* HAS_JOB_CONTROL */ if (CM != 0) { if (tgoto(CM, 2, 2)[0] == 'O') /* OOPS */ CA = 0, CM = 0; else CA = 1, costCM = cost(tgoto(CM, 8, 10)); } else { CA = 0, CM = 0; } costSR = cost(SR); costAL = cost(AL); costDP = cost(tgoto(DOWN_PARM, 10, 10)); costLP = cost(tgoto(LEFT_PARM, 10, 10)); costRP = cost(tgoto(RIGHT_PARM, 10, 10)); PC = xPC ? xPC[0] : 0; aoftspace = tspace; safecp(ttylongname, gettlongname(ltcbuf, type), sizeof ttylongname, "Terminal name too long"); /* proper strings to change tty type */ termreset(); gettmode(); value(REDRAW) = AL && DL; value(OPTIMIZE) = !CA && !GT; if (ospeed == B1200 && !value(REDRAW)) value(SLOWOPEN) = 1; /* see also gettmode above */ if (unknown) serror(catgets(catd, 1, 191, "%s: Unknown terminal type"), type); }
/* Updates inventory based on the current state of event log path */ static int inv_update(sam_fsa_inv_t **invp) { sam_fsa_inv_t *inv; int dir_fd = -1; DIR *dirp = NULL; struct dirent *ent; /* Directory entry */ int i; int rst = 0; struct stat sb; /* Status buffer (stat(2)) */ boolean_t is_changed = FALSE; inv = *invp; if ((dir_fd = open(inv->path_fsa, O_RDONLY, 0)) < 0) { Trace(TR_ERR, "Error opening %s", inv->path_fsa); rst = -1; goto out; } if ((dirp = fdopendir(dir_fd)) == NULL) { Trace(TR_ERR, "Error opening %s from fd.", inv->path_fsa); rst = -1; goto out; } SamMalloc(ent, sizeof (dirent_t) + fpathconf(dir_fd, _PC_NAME_MAX)); /* Mark inventory (looking for deleted files) */ for (i = 0; i < inv->n_logs; i++) { inv->logs[i].status |= fstat_MARK; } /* Loop through files in event log directory. */ while (readdir_r(dirp, ent) != NULL) { if (!is_event_logfile(inv, ent->d_name)) { continue; } if (fstatat(dir_fd, ent->d_name, &sb, AT_SYMLINK_NOFOLLOW) == -1) { Trace(TR_ERR, "lstat(%s/%s) error", inv->path_fsa, ent->d_name); errno = 0; continue; } if (sb.st_size == 0) { continue; /* ignore if empty */ } /* Search inventory for file. */ for (i = 0; i < inv->n_logs; i++) { /* If found unmark and continue */ if (strcmp(ent->d_name, inv->logs[i].name) == 0) { inv->logs[i].status &= ~fstat_MARK; break; } } /* If file not found add to inventory */ if (i >= inv->n_logs) { /* Newly found log file, add to inventory */ inv_add_file(invp, ent->d_name, dir_fd); /* invp might have been realloc'd */ inv = *invp; is_changed = TRUE; } } /* Change status of deleted files */ for (i = 0; i < inv->n_logs; i++) { if (inv->logs[i].status & fstat_MARK) { inv->logs[i].status = fstat_missing; is_changed = TRUE; } } if (is_changed) { inv_save(*invp); } out: NOTNULL_FREE(ent); if (dirp != NULL) { closedir(dirp); } return (rst); }
static int do_test (void) { int ret = 0; static const char *fifo_name = "some-fifo"; size_t filenamelen = strlen (dirbuf) + strlen (fifo_name) + 2; char *filename = xmalloc (filenamelen); snprintf (filename, filenamelen, "%s/%s", dirbuf, fifo_name); /* Create a fifo in the directory. */ int e = mkfifo (filename, 0777); if (e == -1) { printf ("fifo creation failed (%s)\n", strerror (errno)); ret = 1; goto out_nofifo; } long dir_pathconf = pathconf (dirbuf, _PC_PIPE_BUF); if (dir_pathconf < 0) { printf ("pathconf on directory failed: %s\n", strerror (errno)); ret = 1; goto out_nofifo; } long fifo_pathconf = pathconf (filename, _PC_PIPE_BUF); if (fifo_pathconf < 0) { printf ("pathconf on file failed: %s\n", strerror (errno)); ret = 1; goto out_nofifo; } int fifo = open (filename, O_RDONLY | O_NONBLOCK); if (fifo < 0) { printf ("fifo open failed (%s)\n", strerror (errno)); ret = 1; goto out_nofifo; } long dir_fpathconf = fpathconf (dir_fd, _PC_PIPE_BUF); if (dir_fpathconf < 0) { printf ("fpathconf on directory failed: %s\n", strerror (errno)); ret = 1; goto out; } long fifo_fpathconf = fpathconf (fifo, _PC_PIPE_BUF); if (fifo_fpathconf < 0) { printf ("fpathconf on file failed: %s\n", strerror (errno)); ret = 1; goto out; } if (fifo_pathconf != fifo_fpathconf) { printf ("fifo pathconf (%ld) != fifo fpathconf (%ld)\n", fifo_pathconf, fifo_fpathconf); ret = 1; goto out; } if (dir_pathconf != fifo_pathconf) { printf ("directory pathconf (%ld) != fifo pathconf (%ld)\n", dir_pathconf, fifo_pathconf); ret = 1; goto out; } if (dir_fpathconf != fifo_fpathconf) { printf ("directory fpathconf (%ld) != fifo fpathconf (%ld)\n", dir_fpathconf, fifo_fpathconf); ret = 1; goto out; } out: close (fifo); out_nofifo: close (dir_fd); if (unlink (filename) != 0) { printf ("Could not remove fifo (%s)\n", strerror (errno)); ret = 1; } return ret; }
int main(int ac, char **av) { int lc; /* loop counter */ char *msg; /* message returned from parse_opts */ /*************************************************************** * parse standard options ***************************************************************/ if ((msg = parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *)NULL) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); tst_exit(); } /*************************************************************** * perform global setup for test ***************************************************************/ setup(); /* set the expected errnos... */ TEST_EXP_ENOS(exp_enos); /*************************************************************** * check looping state if -c option given ***************************************************************/ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset Tst_count in case we are looping. */ Tst_count = 0; for (i = 0; i < TST_TOTAL; i++) { /* * Call fpathconf(2) with one of the valid arguments in the args array */ TEST(fpathconf(fd, args[i].value)); /* check return code -- if the return value is defined */ if ((TEST_RETURN == -1) && args[i].defined) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "fpathconf(fd, %s) Failed, errno=%d : %s", args[i].define_tag, TEST_ERRNO, strerror(TEST_ERRNO)); } else { /*************************************************************** * only perform functional verification if flag set (-f not given) ***************************************************************/ if (STD_FUNCTIONAL_TEST) { /* No Verification test, yet... */ tst_resm(TPASS, "fpathconf(fd, %s) returned %ld", args[i].define_tag, TEST_RETURN); } } } /* End for i */ } /* End for TEST_LOOPING */ /*************************************************************** * cleanup and exit ***************************************************************/ cleanup(); return 0; } /* End main */
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: #ifdef HAS_LPATHCONF case ACTION_LPATHCONF: #endif { 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; #ifdef HAS_LPATHCONF case ACTION_LPATHCONF: lrval = lpathconf(STR(0), name); break; #endif 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); }
static void * tf2 (void *arg) { int r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("tf2: barrier_wait failed"); exit (1); } pthread_cleanup_push (cl, NULL); const struct aiocb *l[1] = { arg }; struct timespec ts = { .tv_sec = 1000, .tv_nsec = 0 }; TEMP_FAILURE_RETRY (aio_suspend (l, 1, &ts)); pthread_cleanup_pop (0); puts ("tf2: aio_suspend returned"); exit (1); } static int do_test (void) { int fds[2]; if (pipe (fds) != 0) { puts ("pipe failed"); return 1; } struct aiocb a, a2, *ap; char mem[1]; memset (&a, '\0', sizeof (a)); a.aio_fildes = fds[0]; a.aio_buf = mem; a.aio_nbytes = sizeof (mem); if (aio_read (&a) != 0) { puts ("aio_read failed"); return 1; } if (pthread_barrier_init (&b, NULL, 2) != 0) { puts ("barrier_init failed"); return 1; } pthread_t th; if (pthread_create (&th, NULL, tf, &a) != 0) { puts ("1st create failed"); return 1; } int r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); exit (1); } struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 }; while (nanosleep (&ts, &ts) != 0) continue; puts ("going to cancel tf in-time"); if (pthread_cancel (th) != 0) { puts ("1st cancel failed"); return 1; } void *status; if (pthread_join (th, &status) != 0) { puts ("1st join failed"); return 1; } if (status != PTHREAD_CANCELED) { puts ("1st thread not canceled"); return 1; } if (cl_called == 0) { puts ("tf cleanup handler not called"); return 1; } if (cl_called > 1) { puts ("tf cleanup handler called more than once"); return 1; } cl_called = 0; if (pthread_create (&th, NULL, tf2, &a) != 0) { puts ("2nd create failed"); return 1; } r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("2nd barrier_wait failed"); exit (1); } ts.tv_sec = 0; ts.tv_nsec = 100000000; while (nanosleep (&ts, &ts) != 0) continue; puts ("going to cancel tf2 in-time"); if (pthread_cancel (th) != 0) { puts ("2nd cancel failed"); return 1; } if (pthread_join (th, &status) != 0) { puts ("2nd join failed"); return 1; } if (status != PTHREAD_CANCELED) { puts ("2nd thread not canceled"); return 1; } if (cl_called == 0) { puts ("tf2 cleanup handler not called"); return 1; } if (cl_called > 1) { puts ("tf2 cleanup handler called more than once"); return 1; } puts ("in-time cancellation succeeded"); ap = &a; if (aio_cancel (fds[0], &a) != AIO_CANCELED) { puts ("aio_cancel failed"); /* If aio_cancel failed, we cannot reuse aiocb a. */ ap = &a2; } cl_called = 0; size_t len2 = fpathconf (fds[1], _PC_PIPE_BUF); size_t page_size = sysconf (_SC_PAGESIZE); len2 = 20 * (len2 < page_size ? page_size : len2) + sizeof (mem) + 1; char *mem2 = malloc (len2); if (mem2 == NULL) { puts ("could not allocate memory for pipe write"); return 1; } memset (ap, '\0', sizeof (*ap)); ap->aio_fildes = fds[1]; ap->aio_buf = mem2; ap->aio_nbytes = len2; if (aio_write (ap) != 0) { puts ("aio_write failed"); return 1; } if (pthread_create (&th, NULL, tf, ap) != 0) { puts ("3rd create failed"); return 1; } puts ("going to cancel tf early"); if (pthread_cancel (th) != 0) { puts ("3rd cancel failed"); return 1; } r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("3rd barrier_wait failed"); exit (1); } if (pthread_join (th, &status) != 0) { puts ("3rd join failed"); return 1; } if (status != PTHREAD_CANCELED) { puts ("3rd thread not canceled"); return 1; } if (cl_called == 0) { puts ("tf cleanup handler not called"); return 1; } if (cl_called > 1) { puts ("tf cleanup handler called more than once"); return 1; } cl_called = 0; if (pthread_create (&th, NULL, tf2, ap) != 0) { puts ("4th create failed"); return 1; } puts ("going to cancel tf2 early"); if (pthread_cancel (th) != 0) { puts ("4th cancel failed"); return 1; } r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("4th barrier_wait failed"); exit (1); } if (pthread_join (th, &status) != 0) { puts ("4th join failed"); return 1; } if (status != PTHREAD_CANCELED) { puts ("4th thread not canceled"); return 1; } if (cl_called == 0) { puts ("tf2 cleanup handler not called"); return 1; } if (cl_called > 1) { puts ("tf2 cleanup handler called more than once"); return 1; } puts ("early cancellation succeeded"); if (ap == &a2) { /* The aio_read(&a) was not canceled because the read request was already in progress. In the meanwhile aio_write(ap) wrote something to the pipe and the read request either has already been finished or is able to read the requested byte. Wait for the read request before returning from this function because the return value and error code from the read syscall will be written to the struct aiocb a, which lies on the stack of this function. Otherwise the stack from subsequent function calls - e.g. _dl_fini - will be corrupted, which can lead to undefined behaviour like a segmentation fault. */ const struct aiocb *l[1] = { &a }; TEMP_FAILURE_RETRY (aio_suspend(l, 1, NULL)); } return 0; }
static int cacl_get(acl_inp inp, int get_flag, int type, acl_t **aclp) { const char *fname; int fd; int ace_acl = 0; int error; int getcmd, cntcmd; acl_t *acl_info; int save_errno; int stat_error; struct stat64 statbuf; *aclp = NULL; if (type == ACL_PATH) { fname = inp.file; ace_acl = pathconf(fname, _PC_ACL_ENABLED); } else { fd = inp.fd; ace_acl = fpathconf(fd, _PC_ACL_ENABLED); } /* * if acl's aren't supported then * send it through the old GETACL interface */ if (ace_acl == 0 || ace_acl == -1) { ace_acl = _ACL_ACLENT_ENABLED; } if (ace_acl & _ACL_ACE_ENABLED) { cntcmd = ACE_GETACLCNT; getcmd = ACE_GETACL; acl_info = acl_alloc(ACE_T); } else { cntcmd = GETACLCNT; getcmd = GETACL; acl_info = acl_alloc(ACLENT_T); } if (acl_info == NULL) return (-1); if (type == ACL_PATH) { acl_info->acl_cnt = acl(fname, cntcmd, 0, NULL); } else { acl_info->acl_cnt = facl(fd, cntcmd, 0, NULL); } save_errno = errno; if (acl_info->acl_cnt < 0) { acl_free(acl_info); errno = save_errno; return (-1); } if (acl_info->acl_cnt == 0) { acl_free(acl_info); errno = save_errno; return (0); } acl_info->acl_aclp = malloc(acl_info->acl_cnt * acl_info->acl_entry_size); save_errno = errno; if (acl_info->acl_aclp == NULL) { acl_free(acl_info); errno = save_errno; return (-1); } if (type == ACL_PATH) { stat_error = stat64(fname, &statbuf); error = acl(fname, getcmd, acl_info->acl_cnt, acl_info->acl_aclp); } else { stat_error = fstat64(fd, &statbuf); error = facl(fd, getcmd, acl_info->acl_cnt, acl_info->acl_aclp); } save_errno = errno; if (error == -1) { acl_free(acl_info); errno = save_errno; return (-1); } if (stat_error == 0) { acl_info->acl_flags = (S_ISDIR(statbuf.st_mode) ? ACL_IS_DIR : 0); } else acl_info->acl_flags = 0; switch (acl_info->acl_type) { case ACLENT_T: if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; case ACE_T: if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; default: errno = EINVAL; acl_free(acl_info); return (-1); } if ((acl_info->acl_flags & ACL_IS_TRIVIAL) && (get_flag & ACL_NO_TRIVIAL)) { acl_free(acl_info); errno = 0; return (0); } *aclp = acl_info; return (0); }
int FPathConfTest (void) { int error = 0, retval = TRUE; int fd = -1; error = fpathconf(fd, _PC_LINK_MAX); if (error == -1) { fd = open("testfile1.tst", O_RDWR); error = fpathconf(fd, _PC_LINK_MAX); error = fpathconf(fd, _PC_MAX_CANON); error = fpathconf(fd, _PC_MAX_INPUT); error = fpathconf(fd, _PC_NAME_MAX); error = fpathconf(fd, _PC_PATH_MAX); error = fpathconf(fd, _PC_PIPE_BUF); error = fpathconf(fd, _PC_CHOWN_RESTRICTED); error = fpathconf(fd, _PC_NO_TRUNC); error = fpathconf(fd, _PC_VDISABLE); error = fpathconf(fd, _PC_ASYNC_IO); error = fpathconf(fd, _PC_PRIO_IO); error = fpathconf(fd, _PC_SYNC_IO); error = fpathconf(fd, 255); close(fd); fd = open("testfile1.tst", O_WRONLY); error = fpathconf(fd, _PC_LINK_MAX); retval = TRUE; } else retval = FALSE; /* assert (retval == TRUE);*/ return(retval); }