Index: lib/libc/sys/Makefile.inc =================================================================== --- lib/libc/sys/Makefile.inc +++ lib/libc/sys/Makefile.inc @@ -475,7 +475,8 @@ setuid.2 seteuid.2 \ setuid.2 setgid.2 MLINKS+=shmat.2 shmdt.2 -MLINKS+=shm_open.2 shm_unlink.2 +MLINKS+=shm_open.2 shm_unlink.2 \ + shm_open.2 shm_rename.2 MLINKS+=sigwaitinfo.2 sigtimedwait.2 MLINKS+=stat.2 fstat.2 \ stat.2 fstatat.2 \ Index: lib/libc/sys/Symbol.map =================================================================== --- lib/libc/sys/Symbol.map +++ lib/libc/sys/Symbol.map @@ -408,6 +408,7 @@ fhreadlink; getfhat; funlinkat; + shm_rename; }; FBSDprivate_1.0 { Index: lib/libc/sys/shm_open.2 =================================================================== --- lib/libc/sys/shm_open.2 +++ lib/libc/sys/shm_open.2 @@ -32,7 +32,7 @@ .Dt SHM_OPEN 2 .Os .Sh NAME -.Nm shm_open , shm_unlink +.Nm shm_open , shm_rename , shm_unlink .Nd "shared memory object operations" .Sh LIBRARY .Lb libc @@ -43,6 +43,8 @@ .Ft int .Fn shm_open "const char *path" "int flags" "mode_t mode" .Ft int +.Fn shm_rename "const char *path_from" "const char *path_to" +.Ft int .Fn shm_unlink "const char *path" .Sh DESCRIPTION The @@ -121,6 +123,8 @@ Since the object has no name, it cannot be removed via a subsequent call to .Fn shm_unlink . +or moved with a call to +.Fn shm_rename . Instead, the shared memory object will be garbage collected when the last reference to the shared memory object is removed. @@ -136,6 +140,17 @@ All other flags are ignored. .Pp The +.Fn shm_rename +system call atomically removes a shared memory object named +.Fa path_from +and relinks it at +.Fa path_to . +If another object is already linked at +.Fa path_to , +that object will be unlinked first. +This is also a FreeBSD extension. +.Pp +The .Fn shm_unlink system call removes a shared memory object named .Fa path . @@ -144,15 +159,20 @@ .Fn shm_open returns a non-negative integer, and +.Fn shm_rename +and .Fn shm_unlink -returns zero. -Both functions return -1 on failure, and set +return zero. +All functions return -1 on failure, and set .Va errno to indicate the error. .Sh COMPATIBILITY The -.Fa path -argument does not necessarily represent a pathname (although it does in +.Fa path , +.Fa path_from , +and +.Fa path_to +arguments do not necessarily represent a pathname (although they do in most other implementations). Two processes opening the same .Fa path @@ -265,6 +285,25 @@ The required permissions (for reading or reading and writing) are denied. .El .Pp +The following errors are defined for +.Fn shm_rename : +.Bl -tag -width Er +.It Bq Er EFAULT +The +.Fa path_from +or +.Fa path_to +argument points outside the process' allocated address space. +.It Bq Er ENAMETOOLONG +The entire pathname exceeded 1023 characters. +.It Bq Er ENOENT +The shared memory object at +.Fa path_from +does not exist. +.It Bq Er EACCES +The required permissions are denied. +.El +.Pp .Fn shm_unlink fails with these error codes for these conditions: .Bl -tag -width Er @@ -305,6 +344,9 @@ The functions were reimplemented as system calls using shared memory objects directly rather than files in .Fx 8.0 . +.Pp +.Fn shm_rename +first appeared in FreeBSD 13.0 as a FreeBSD-specific extension. .Sh AUTHORS .An Garrett A. Wollman Aq Mt wollman@FreeBSD.org (C library support and this manual page) @@ -311,3 +353,6 @@ .Pp .An Matthew Dillon Aq Mt dillon@FreeBSD.org .Pq Dv MAP_NOSYNC +.Pp +.An Matthew Bryan Aq Mt matthew.bryan@isilon.com +.Pq Dv shm_rename implementation Index: sys/compat/freebsd32/freebsd32_syscall.h =================================================================== --- sys/compat/freebsd32/freebsd32_syscall.h +++ sys/compat/freebsd32/freebsd32_syscall.h @@ -496,4 +496,5 @@ #define FREEBSD32_SYS_fhreadlink 567 #define FREEBSD32_SYS_funlinkat 568 #define FREEBSD32_SYS_copy_file_range 569 -#define FREEBSD32_SYS_MAXSYSCALL 570 +#define FREEBSD32_SYS_shm_rename 570 +#define FREEBSD32_SYS_MAXSYSCALL 571 Index: sys/compat/freebsd32/freebsd32_syscalls.c =================================================================== --- sys/compat/freebsd32/freebsd32_syscalls.c +++ sys/compat/freebsd32/freebsd32_syscalls.c @@ -606,4 +606,5 @@ "fhreadlink", /* 567 = fhreadlink */ "funlinkat", /* 568 = funlinkat */ "copy_file_range", /* 569 = copy_file_range */ + "shm_rename", /* 570 = shm_rename */ }; Index: sys/compat/freebsd32/freebsd32_sysent.c =================================================================== --- sys/compat/freebsd32/freebsd32_sysent.c +++ sys/compat/freebsd32/freebsd32_sysent.c @@ -653,4 +653,5 @@ { AS(fhreadlink_args), (sy_call_t *)sys_fhreadlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 567 = fhreadlink */ { AS(funlinkat_args), (sy_call_t *)sys_funlinkat, AUE_UNLINKAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 568 = funlinkat */ { AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */ + { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 570 = shm_rename */ }; Index: sys/compat/freebsd32/freebsd32_systrace_args.c =================================================================== --- sys/compat/freebsd32/freebsd32_systrace_args.c +++ sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3332,6 +3332,14 @@ *n_args = 6; break; } + /* shm_rename */ + case 570: { + struct shm_rename_args *p = params; + uarg[0] = (intptr_t) p->path_from; /* const char * */ + uarg[1] = (intptr_t) p->path_to; /* const char * */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -8971,6 +8979,19 @@ break; }; break; + /* shm_rename */ + case 570: + switch(ndx) { + case 0: + p = "userland const char *"; + break; + case 1: + p = "userland const char *"; + break; + default: + break; + }; + break; default: break; }; @@ -10850,6 +10871,11 @@ if (ndx == 0 || ndx == 1) p = "ssize_t"; break; + /* shm_rename */ + case 570: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; Index: sys/compat/freebsd32/syscalls.master =================================================================== --- sys/compat/freebsd32/syscalls.master +++ sys/compat/freebsd32/syscalls.master @@ -1150,5 +1150,6 @@ 569 AUE_NULL NOPROTO { ssize_t copy_file_range(int infd, \ off_t *inoffp, int outfd, off_t *outoffp, \ size_t len, unsigned int flags); } +570 AUE_NULL NOPROTO { int shm_rename(const char *path_from, const char *path_to); } ; vim: syntax=off Index: sys/kern/init_sysent.c =================================================================== --- sys/kern/init_sysent.c +++ sys/kern/init_sysent.c @@ -619,4 +619,5 @@ { AS(fhreadlink_args), (sy_call_t *)sys_fhreadlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 567 = fhreadlink */ { AS(funlinkat_args), (sy_call_t *)sys_funlinkat, AUE_UNLINKAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 568 = funlinkat */ { AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */ + { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 570 = shm_rename */ }; Index: sys/kern/syscalls.c =================================================================== --- sys/kern/syscalls.c +++ sys/kern/syscalls.c @@ -576,4 +576,5 @@ "fhreadlink", /* 567 = fhreadlink */ "funlinkat", /* 568 = funlinkat */ "copy_file_range", /* 569 = copy_file_range */ + "shm_rename", /* 570 = shm_rename */ }; Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -3185,6 +3185,11 @@ unsigned int flags ); } +570 AUE_NULL STD { + int shm_rename( + _In_z_ const char *path_from, + _In_z_ const char *path_to); + } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: sys/kern/systrace_args.c =================================================================== --- sys/kern/systrace_args.c +++ sys/kern/systrace_args.c @@ -3324,6 +3324,14 @@ *n_args = 6; break; } + /* shm_rename */ + case 570: { + struct shm_rename_args *p = params; + uarg[0] = (intptr_t) p->path_from; /* const char * */ + uarg[1] = (intptr_t) p->path_to; /* const char * */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -8876,6 +8884,19 @@ break; }; break; + /* shm_rename */ + case 570: + switch(ndx) { + case 0: + p = "userland const char *"; + break; + case 1: + p = "userland const char *"; + break; + default: + break; + }; + break; default: break; }; @@ -10782,6 +10803,11 @@ if (ndx == 0 || ndx == 1) p = "ssize_t"; break; + /* shm_rename */ + case 570: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; Index: sys/kern/uipc_shm.c =================================================================== --- sys/kern/uipc_shm.c +++ sys/kern/uipc_shm.c @@ -33,8 +33,9 @@ /* * Support for shared swap-backed anonymous memory objects via - * shm_open(2) and shm_unlink(2). While most of the implementation is - * here, vm_mmap.c contains mapping logic changes. + * shm_open(2), shm_rename(2), and shm_unlink(2). + * While most of the implementation is here, vm_mmap.c contains + * mapping logic changes. * * posixshmcontrol(1) allows users to inspect the state of the memory * objects. Per-uid swap resource limit controls total amount of @@ -118,7 +119,8 @@ static void shm_init(void *arg); static void shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd); static struct shmfd *shm_lookup(char *path, Fnv32_t fnv); -static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred); +static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred, + bool preserve); static fo_rdwr_t shm_read; static fo_rdwr_t shm_write; @@ -665,7 +667,7 @@ } static int -shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred) +shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred, bool preserve) { struct shm_mapping *map; int error; @@ -685,7 +687,8 @@ return (error); map->sm_shmfd->shm_path = NULL; LIST_REMOVE(map, sm_link); - shm_drop(map->sm_shmfd); + if (!preserve) + shm_drop(map->sm_shmfd); free(map->sm_path, M_SHMFD); free(map, M_SHMFD); return (0); @@ -881,7 +884,7 @@ AUDIT_ARG_UPATH1_CANON(path); fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&shm_dict_lock); - error = shm_remove(path, fnv, td->td_ucred); + error = shm_remove(path, fnv, td->td_ucred, false); sx_xunlock(&shm_dict_lock); free(path, M_TEMP); @@ -888,7 +891,108 @@ return (error); } +/* + * TODO: add a 'flags' argument, similar to the Linux renameat2. + * The flag states what should happen if there is an shm already at path_to. + * That way we have the option to e.g. return EEXIST instead of unlinking + * the shm at path_to. We could also have an option to swap the two shms. + */ int +sys_shm_rename(struct thread *td, struct shm_rename_args *uap) +{ + char *path_from = NULL, *path_to = NULL; + Fnv32_t fnv_from, fnv_to; + struct shmfd *fd_from; + int error; + + path_from = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + error = copyinstr(uap->path_from, path_from, MAXPATHLEN, NULL); + if (error) + goto out; + + /* + * Malloc zone M_SHMFD, since this path may end up freed later from + * M_SHMFD. + */ + path_to = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); + error = copyinstr(uap->path_to, path_to, MAXPATHLEN, NULL); + if (error) + goto out; + + /* Rename with from/to equal is a no-op */ + if (strncmp(path_from, path_to, MAXPATHLEN) == 0) + goto out; + + fnv_from = fnv_32_str(path_from, FNV1_32_INIT); + fnv_to = fnv_32_str(path_to, FNV1_32_INIT); + + sx_xlock(&shm_dict_lock); + + fd_from = shm_lookup(path_from, fnv_from); + if (fd_from == NULL) { + sx_xunlock(&shm_dict_lock); + error = ENOENT; + goto out; + } + + error = shm_remove(path_from, fnv_from, td->td_ucred, true); + + /* + * One of my assumptions failed if ENOENT (e.g. locking didn't + * protect us) + */ + KASSERT(error != ENOENT, ("Our shm disappeared during shm_rename: %s", + path_from)); + if (error) { + sx_xunlock(&shm_dict_lock); + goto out; + } + + /* + * NOTE: if path_to is not already in the hash, c'est la vie; + * it simply means we have nothing already at path_to to unlink. + * That is the ENOENT case. + * + * If we somehow don't have access to unlink this guy, but + * did for the shm at path_from, then relink the shm to path_from + * and abort with EACCES. + */ + error = shm_remove(path_to, fnv_to, td->td_ucred, false); + if (error == EACCES) { + shm_insert(path_from, fnv_from, fd_from); + /* Don't free path_from now, since the hash references it */ + path_from = NULL; + sx_xunlock(&shm_dict_lock); + goto out; + } + else if (error && error != ENOENT) { + sx_xunlock(&shm_dict_lock); + goto out; + } + + shm_insert(path_to, fnv_to, fd_from); + + /* Don't free path_to now, since the hash references it */ + path_to = NULL; + + /* We kept a ref when we removed, and incremented again in insert */ + shm_drop(fd_from); +#ifdef DEBUG + KASSERT(fd_from->shm_refs > 0, ("Expected >0 refs; got: %d\n", + fd_from->shm_refs)); +#endif + + sx_xunlock(&shm_dict_lock); + +out: + if (path_from != NULL) + free(path_from, M_TEMP); + if (path_to != NULL) + free(path_to, M_SHMFD); + return(error); +} + +int shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, vm_prot_t prot, vm_prot_t cap_maxprot, int flags, vm_ooffset_t foff, struct thread *td) Index: sys/sys/mman.h =================================================================== --- sys/sys/mman.h +++ sys/sys/mman.h @@ -281,6 +281,7 @@ int mlockall(int); int munlockall(void); int shm_open(const char *, int, mode_t); +int shm_rename(const char *, const char *); int shm_unlink(const char *); #endif __END_DECLS Index: sys/sys/syscall.h =================================================================== --- sys/sys/syscall.h +++ sys/sys/syscall.h @@ -505,4 +505,5 @@ #define SYS_fhreadlink 567 #define SYS_funlinkat 568 #define SYS_copy_file_range 569 -#define SYS_MAXSYSCALL 570 +#define SYS_shm_rename 570 +#define SYS_MAXSYSCALL 571 Index: sys/sys/syscall.mk =================================================================== --- sys/sys/syscall.mk +++ sys/sys/syscall.mk @@ -410,4 +410,5 @@ fhlinkat.o \ fhreadlink.o \ funlinkat.o \ - copy_file_range.o + copy_file_range.o \ + shm_rename.o Index: sys/sys/sysproto.h =================================================================== --- sys/sys/sysproto.h +++ sys/sys/sysproto.h @@ -1804,6 +1804,10 @@ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char flags_l_[PADL_(unsigned int)]; unsigned int flags; char flags_r_[PADR_(unsigned int)]; }; +struct shm_rename_args { + char path_from_l_[PADL_(const char *)]; const char * path_from; char path_from_r_[PADR_(const char *)]; + char path_to_l_[PADL_(const char *)]; const char * path_to; char path_to_r_[PADR_(const char *)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2190,6 +2194,7 @@ int sys_fhreadlink(struct thread *, struct fhreadlink_args *); int sys_funlinkat(struct thread *, struct funlinkat_args *); int sys_copy_file_range(struct thread *, struct copy_file_range_args *); +int sys_shm_rename(struct thread *, struct shm_rename_args *); #ifdef COMPAT_43 @@ -3098,6 +3103,7 @@ #define SYS_AUE_fhreadlink AUE_NULL #define SYS_AUE_funlinkat AUE_UNLINKAT #define SYS_AUE_copy_file_range AUE_NULL +#define SYS_AUE_shm_rename AUE_NULL #undef PAD_ #undef PADL_ Index: tests/sys/posixshm/posixshm_test.c =================================================================== --- tests/sys/posixshm/posixshm_test.c +++ tests/sys/posixshm/posixshm_test.c @@ -46,20 +46,36 @@ #define TEST_PATH_LEN 256 static char test_path[TEST_PATH_LEN]; +static char test_path2[TEST_PATH_LEN]; +static unsigned int test_path_idx = 0; static void -gen_test_path(void) +gen_a_test_path(char *path) { + snprintf(path, TEST_PATH_LEN, "%s/tmp.XXXXXX%d", + getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"), + test_path_idx); - snprintf(test_path, sizeof(test_path), "%s/tmp.XXXXXX", - getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")); - test_path[sizeof(test_path) - 1] = '\0'; - ATF_REQUIRE_MSG(mkstemp(test_path) != -1, + test_path_idx++; + + ATF_REQUIRE_MSG(mkstemp(path) != -1, "mkstemp failed; errno=%d", errno); - ATF_REQUIRE_MSG(unlink(test_path) == 0, + ATF_REQUIRE_MSG(unlink(path) == 0, "unlink failed; errno=%d", errno); } +static void +gen_test_path(void) +{ + gen_a_test_path(test_path); +} + +static void +gen_test_path2(void) +{ + gen_a_test_path(test_path2); +} + /* * Attempt a shm_open() that should fail with an expected error of 'error'. */ @@ -89,20 +105,18 @@ } /* - * Open the test object and write '1' to the first byte. Returns valid fd + * Open the test object and write a value to the first byte. Returns valid fd * on success and -1 on failure. */ static int -scribble_object(void) +scribble_object(const char *path, char value) { char *page; int fd, pagesize; - gen_test_path(); - ATF_REQUIRE(0 < (pagesize = getpagesize())); - fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777); + fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777); if (fd < 0 && errno == EEXIST) { if (shm_unlink(test_path) < 0) atf_tc_fail("shm_unlink"); @@ -117,7 +131,7 @@ if (page == MAP_FAILED) atf_tc_fail("mmap failed; errno=%d", errno); - page[0] = '1'; + page[0] = value; ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", errno); @@ -124,6 +138,34 @@ return (fd); } +/* + * Fail the test case if the 'path' does not refer to an shm whose first byte + * is equal to expected_value + */ +static void +verify_object(const char *path, char expected_value) +{ + int fd; + int pagesize; + char *page; + + ATF_REQUIRE(0 < (pagesize = getpagesize())); + + fd = shm_open(path, O_RDONLY, 0777); + if (fd < 0) + atf_tc_fail("shm_open failed; errno=%d", errno); + + page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); + if (page == MAP_FAILED) + atf_tc_fail("mmap(1)"); + if (page[0] != expected_value) + atf_tc_fail("Renamed object has incorrect value; has %d, " + "expected %d\n", page[0], expected_value); + ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", + errno); + close(fd); +} + ATF_TC_WITHOUT_HEAD(remap_object); ATF_TC_BODY(remap_object, tc) { @@ -132,7 +174,8 @@ ATF_REQUIRE(0 < (pagesize = getpagesize())); - fd = scribble_object(); + gen_test_path(); + fd = scribble_object(test_path, '1'); page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (page == MAP_FAILED) @@ -149,6 +192,86 @@ "shm_unlink failed; errno=%d", errno); } +ATF_TC_WITHOUT_HEAD(rename_from_anon); +ATF_TC_BODY(rename_from_anon, tc) +{ + int fd; + + gen_test_path(); + fd = shm_rename(SHM_ANON, test_path); + if (fd >= 0) + atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly"); +} + +ATF_TC_WITHOUT_HEAD(rename_from_nonexisting); +ATF_TC_BODY(rename_from_nonexisting, tc) +{ + int fd; + + gen_test_path(); + fd = shm_rename(test_path, test_path2); + if (fd >= 0) + atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); + + if (errno != ENOENT) + atf_tc_fail("Expected ENOENT to rename of nonexistent shm"); +} + +ATF_TC_WITHOUT_HEAD(rename_to_anon); +ATF_TC_BODY(rename_to_anon, tc) +{ + int fd; + + gen_test_path(); + fd = shm_rename(test_path, SHM_ANON); + if (fd >= 0) + atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly"); +} + +ATF_TC_WITHOUT_HEAD(rename_to_existing); +ATF_TC_BODY(rename_to_existing, tc) +{ + char expected_value; + int fd; + int fd2; + + // Some contents we can verify later + expected_value = 'g'; + + gen_test_path(); + fd = scribble_object(test_path, expected_value); + close(fd); + + // Give the other some different value so we can detect success + gen_test_path2(); + fd2 = scribble_object(test_path2, 'h'); + close(fd2); + + ATF_REQUIRE_MSG(shm_rename(test_path, test_path2) == 0, + "shm_rename failed; errno=%d", errno); + + // Read back renamed; verify contents + verify_object(test_path2, expected_value); +} + +ATF_TC_WITHOUT_HEAD(rename_to_self); +ATF_TC_BODY(rename_to_self, tc) +{ + int fd; + char expected_value; + + expected_value = 't'; + + gen_test_path(); + fd = scribble_object(test_path, expected_value); + close(fd); + + ATF_REQUIRE_MSG(shm_rename(test_path, test_path) == 0, + "shm_rename failed; errno=%d", errno); + + verify_object(test_path, expected_value); +} + ATF_TC_WITHOUT_HEAD(reopen_object); ATF_TC_BODY(reopen_object, tc) { @@ -157,7 +280,8 @@ ATF_REQUIRE(0 < (pagesize = getpagesize())); - fd = scribble_object(); + gen_test_path(); + fd = scribble_object(test_path, '1'); close(fd); fd = shm_open(test_path, O_RDONLY, 0777); @@ -613,6 +737,11 @@ { ATF_TP_ADD_TC(tp, remap_object); + ATF_TP_ADD_TC(tp, rename_from_anon); + ATF_TP_ADD_TC(tp, rename_from_nonexisting); + ATF_TP_ADD_TC(tp, rename_to_anon); + ATF_TP_ADD_TC(tp, rename_to_existing); + ATF_TP_ADD_TC(tp, rename_to_self); ATF_TP_ADD_TC(tp, reopen_object); ATF_TP_ADD_TC(tp, readonly_mmap_write); ATF_TP_ADD_TC(tp, open_after_link); Index: usr.bin/truss/syscalls.c =================================================================== --- usr.bin/truss/syscalls.c +++ usr.bin/truss/syscalls.c @@ -470,6 +470,8 @@ { Ptr | IN, 3 }, { Socklent, 4 } } }, { .name = "shm_open", .ret_type = 1, .nargs = 3, .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, + { .name = "shm_rename", .ret_type = 1, .nargs = 2, + .args = { { Name | IN, 0 }, { Name | IN, 1 } } }, { .name = "shm_unlink", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "shutdown", .ret_type = 1, .nargs = 2,