[RFC,2/3] hurd: Implement O_TMPFILE

Message ID 20221212114636.74222-3-bugaevc@gmail.com
State Superseded, archived
Headers
Series O_TMPFILE and SHM_ANON for the Hurd |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Sergey Bugaev Dec. 12, 2022, 11:46 a.m. UTC
  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.
---
 hurd/lookup-at.c               | 20 ++++++++++++++++++++
 sysdeps/mach/hurd/bits/fcntl.h |  5 +++++
 2 files changed, 25 insertions(+)
  

Comments

Samuel Thibault Jan. 29, 2023, 11:25 p.m. UTC | #1
Hello,

Sergey Bugaev, le lun. 12 déc. 2022 14:46:35 +0300, a ecrit:
> diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
> index 17dcb384..b898a0c5 100644
> --- a/sysdeps/mach/hurd/bits/fcntl.h
> +++ b/sysdeps/mach/hurd/bits/fcntl.h
> @@ -123,6 +123,11 @@
>  # define O_CLOEXEC	0x00400000 /* Set FD_CLOEXEC.  */
>  #endif
>  
> +#ifdef __USE_GNU
> +# define __O_TMPFILE	0x00800000 /* Make a new unnamed file.  */
> +# define O_TMPFILE	(__O_TMPFILE | O_DIRECTORY)
> +#endif

I don't think we need the __O_TMPFILE variant, only the O_TMPFILE one?

Linux uses __ variants just because it has per-arch definitions.

Samuel
  
Sergey Bugaev Jan. 30, 2023, 9:53 a.m. UTC | #2
On Mon, Jan 30, 2023 at 2:25 AM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Hello,
>
> Sergey Bugaev, le lun. 12 déc. 2022 14:46:35 +0300, a ecrit:
> > diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
> > index 17dcb384..b898a0c5 100644
> > --- a/sysdeps/mach/hurd/bits/fcntl.h
> > +++ b/sysdeps/mach/hurd/bits/fcntl.h
> > @@ -123,6 +123,11 @@
> >  # define O_CLOEXEC   0x00400000 /* Set FD_CLOEXEC.  */
> >  #endif
> >
> > +#ifdef __USE_GNU
> > +# define __O_TMPFILE 0x00800000 /* Make a new unnamed file.  */
> > +# define O_TMPFILE   (__O_TMPFILE | O_DIRECTORY)
> > +#endif
>
> I don't think we need the __O_TMPFILE variant, only the O_TMPFILE one?
>
> Linux uses __ variants just because it has per-arch definitions.

This was an attempt to mimic the Linux port's behavior, where it
automatically or's in O_DIRECTORY when you specify O_TMPFILE. Not that
it has any real meaning (at least for us) since my
__file_name_lookup_at () passes O_DIRECTORY automatically (instead of
any other flags) when O_TMPFILE is used. So should I remove this and
just have

# define O_TMPFILE 0x00800000 /* Make a new unnamed file.  */

?

Thanks for taking a look!

Sergey
  
Samuel Thibault Jan. 30, 2023, 9:59 a.m. UTC | #3
Sergey Bugaev, le lun. 30 janv. 2023 12:53:02 +0300, a ecrit:
> So should I remove this and just have
> 
> # define O_TMPFILE 0x00800000 /* Make a new unnamed file.  */
> 
> ?

Yes, I believe we don't need the __ variant.

Samuel
  

Patch

diff --git a/hurd/lookup-at.c b/hurd/lookup-at.c
index 2b84dfd6..42ac8c42 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) == __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,21 @@  __file_name_lookup_at (int fd, int at_flags,
         }
     }
 
+  if ((orig_flags & __O_TMPFILE) == __O_TMPFILE)
+    {
+      /* What we have looked up is not the file iteself, but actually
+         the directory to create the file in.  Do that now.  */
+      file_t dir = result;
+
+      err = __dir_mkfile (dir, orig_flags & ~O_TMPFILE, mode, &result);
+      __mach_port_deallocate (__mach_task_self (), dir);
+      if (err)
+        {
+          __hurd_fail (err);
+          return MACH_PORT_NULL;
+        }
+    }
+
   return result;
 }
 
diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
index 17dcb384..b898a0c5 100644
--- a/sysdeps/mach/hurd/bits/fcntl.h
+++ b/sysdeps/mach/hurd/bits/fcntl.h
@@ -123,6 +123,11 @@ 
 # define O_CLOEXEC	0x00400000 /* Set FD_CLOEXEC.  */
 #endif
 
+#ifdef __USE_GNU
+# define __O_TMPFILE	0x00800000 /* Make a new unnamed file.  */
+# define O_TMPFILE	(__O_TMPFILE | O_DIRECTORY)
+#endif
+
 
 /* Controlling terminal flags.  These are understood only by `open',
    and are not preserved once the file has been opened.  */