Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142011528
D21423.id61414.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D21423.id61414.diff
View Options
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,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 15, 9:46 PM (10 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27655145
Default Alt Text
D21423.id61414.diff (21 KB)
Attached To
Mode
D21423: Add an shm_rename syscall
Attached
Detach File
Event Timeline
Log In to Comment