aboutsummaryrefslogtreecommitdiff
path: root/hurd/lookup-at.c
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2023-01-30 15:52:15 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-02-01 23:32:21 +0100
commit65392c84782a53b0d7705ca0207c95c3da41c7dc (patch)
treeace56ea31baef53a4e2d7b5f2ff412664bbada3e /hurd/lookup-at.c
parentd011ab5708c2be4e2cc7eb8851c9e2c614410bd3 (diff)
downloadglibc-65392c84782a53b0d7705ca0207c95c3da41c7dc.zip
glibc-65392c84782a53b0d7705ca0207c95c3da41c7dc.tar.gz
glibc-65392c84782a53b0d7705ca0207c95c3da41c7dc.tar.bz2
hurd: Implement O_TMPFILE
This is a flag that causes open () to create a new, unnamed file in the same filesystem as the given directory. The file descriptor can be simply used in the creating process as a temporary file, or shared with children processes via fork (), or sent over a Unix socket. The file can be left anonymous, in which case it will be deleted from the backing file system once all copies of the file descriptor are closed, or given a permanent name with a linkat () call, such as the following: int fd = open ("/tmp", O_TMPFILE | O_RDWR, 0700); /* Do something with the file... */ linkat (fd, "", AT_FDCWD, "/tmp/filename", AT_EMPTY_PATH); In between creating the file and linking it to the file system, it is possible to set the file content, mode, ownership, author, and other attributes, so that the file visibly appears in the file system (perhaps replacing another file) atomically, with all of its attributes already set up. The Hurd support for O_TMPFILE directly exposes the dir_mkfile RPC to user programs. Previously, dir_mkfile was used by glibc internally, in particular for implementing tmpfile (), but not exposed to user programs through a Unix-level API. O_TMPFILE was initially introduced by Linux. This implementation is intended to be compatible with the Linux implementation, except that the O_EXCL flag is not given the special meaning when used together with O_TMPFILE, unlike on Linux. Signed-off-by: Sergey Bugaev <bugaevc@gmail.com> Message-Id: <20230130125216.6254-3-bugaevc@gmail.com>
Diffstat (limited to 'hurd/lookup-at.c')
-rw-r--r--hurd/lookup-at.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/hurd/lookup-at.c b/hurd/lookup-at.c
index 25dab5a..88c8377 100644
--- a/hurd/lookup-at.c
+++ b/hurd/lookup-at.c
@@ -29,6 +29,7 @@ __file_name_lookup_at (int fd, int at_flags,
error_t err;
file_t result;
int empty = at_flags & AT_EMPTY_PATH;
+ int orig_flags;
at_flags &= ~AT_EMPTY_PATH;
@@ -53,6 +54,10 @@ __file_name_lookup_at (int fd, int at_flags,
return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
}
+ orig_flags = flags;
+ if (flags & O_TMPFILE)
+ flags = O_DIRECTORY;
+
if (fd == AT_FDCWD || file_name[0] == '/')
{
err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0,
@@ -90,6 +95,22 @@ __file_name_lookup_at (int fd, int at_flags,
}
}
+ if (orig_flags & O_TMPFILE)
+ {
+ /* What we have looked up is not the file itself, but actually
+ the directory to create the file in. Do that now. */
+ file_t dir = result;
+
+ err = __dir_mkfile (dir, orig_flags & ~(O_TMPFILE | O_DIRECTORY),
+ mode, &result);
+ __mach_port_deallocate (__mach_task_self (), dir);
+ if (err)
+ {
+ __hurd_fail (err);
+ return MACH_PORT_NULL;
+ }
+ }
+
return result;
}