all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob 6f9c2c5b4e4e552b91670ca2d2d35ea1707adea0 10886 bytes (raw)
name: gnu/packages/patches/guile-openat-and-friends-13.patch 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
 
Guix-Upstream: https://lists.gnu.org/archive/html/guile-devel/2021-11/msg00005.html
From: Maxime Devos <maximedevos@telenet.be>
Subject: [PATCH v2 13/14] =?UTF-8?q?Define=20Scheme=20bindings=20to=20?=
 =?UTF-8?q?=E2=80=98openat=E2=80=99=20when=20available.?=
Date: Tue, 16 Nov 2021 11:06:36 +0000
Message-Id: <20211116110637.125579-14-maximedevos@telenet.be>
In-Reply-To: <20211116110637.125579-1-maximedevos@telenet.be>
References: <175c3a6572e832d84927937b309a3095cadf5702.camel@telenet.be>
 <20211116110637.125579-1-maximedevos@telenet.be>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* configure.ac: Detect if ‘openat’ is defined.
* libguile/filesys.c
  (flags_to_mode): Extract from ...
  (scm_mode): ... here.
  (scm_open_fdes_at, scm_openat): Define the Scheme bindings.
* libguile/filesys.h (scm_open_fdes_at, scm_openat): Make them part
  of the API.
* doc/ref/posix.texi (File System): Document them.
* test-suite/tests/filesys.test ("openat"): Test ‘openat’.
* libguile/syscalls.h (openat_or_openat64): Decide between ‘openat’
  and ‘openat64’.
---
 configure.ac                  |  3 +-
 doc/ref/posix.texi            | 13 +++++
 libguile/filesys.c            | 96 +++++++++++++++++++++++++++--------
 libguile/filesys.h            |  2 +
 libguile/syscalls.h           |  1 +
 test-suite/tests/filesys.test | 73 ++++++++++++++++++++++++++
 6 files changed, 167 insertions(+), 21 deletions(-)

diff --git a/configure.ac b/configure.ac
index e073e04f4..905e4d465 100644
--- a/configure.ac
+++ b/configure.ac
@@ -478,7 +478,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
 #   isblank - available as a GNU extension or in C99
 #   _NSGetEnviron - Darwin specific
 #   strcoll_l, newlocale, uselocale, utimensat, futimens, fchmodat,
-#   unlinkat, fchownat, fstatat - POSIX.1-2008
+#   unlinkat, fchownat, fstatat, openat - POSIX.1-2008
 #   strtol_l - non-POSIX, found in glibc
 #   fork - unavailable on Windows
 #   sched_getaffinity, sched_setaffinity - GNU extensions (glibc)
@@ -495,6 +495,7 @@ AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid         \
   getgrent kill getppid getpgrp fork setitimer getitimer strchr strcmp  \
   index bcopy memcpy rindex truncate isblank _NSGetEnviron              \
   strcoll strcoll_l strtod_l strtol_l newlocale uselocale utimensat     \
+  openat \
   fstatat futimens sched_getaffinity sched_setaffinity sendfile])
 
 # The newlib C library uses _NL_ prefixed locale langinfo constants.
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index cdd03f141..3619ee2c3 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -296,12 +296,25 @@ Create the file if it does not already exist.
 for additional flags.
 @end deffn
 
+@deffn {Scheme Procedure} openat dir path flags [mode]
+@deffnx {C Function} scm_openat (dir, path, flags, mode)
+Similar to @code{open}, but resolve the file name @var{path}
+relative to the directory referred to by the file port @var{dir}
+instead.
+@end deffn
+
 @deffn {Scheme Procedure} open-fdes path flags [mode]
 @deffnx {C Function} scm_open_fdes (path, flags, mode)
 Similar to @code{open} but return a file descriptor instead of
 a port.
 @end deffn
 
+@deffn {Scheme Procedure} open-fdes-at dir path flags [mode]
+@deffnx {C Function} scm_open_fdes_at (dir, path, flags, mode)
+Similar to @code{openat}, but return a file descriptor instead
+of a port.
+@end deffn
+
 @deffn {Scheme Procedure} close fd_or_port
 @deffnx {C Function} scm_close (fd_or_port)
 Similar to @code{close-port} (@pxref{Ports, close-port}),
diff --git a/libguile/filesys.c b/libguile/filesys.c
index d045a672f..dadbe3393 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -249,6 +249,60 @@ SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0,
 }
 #undef FUNC_NAME
 
+#ifdef HAVE_OPENAT
+SCM_DEFINE (scm_open_fdes_at, "open-fdes-at", 3, 1, 0,
+            (SCM dir, SCM path, SCM flags, SCM mode),
+            "Similar to @code{openat}, but return a file descriptor instead\n"
+            "of a port.")
+#define FUNC_NAME s_scm_open_fdes_at
+{
+  int dir_fdes;
+  int fd;
+  int iflags;
+  int imode;
+
+  iflags = SCM_NUM2INT (SCM_ARG2, flags);
+  imode = SCM_NUM2INT_DEF (3, mode, 0666);
+  SCM_VALIDATE_OPFPORT (SCM_ARG1, dir);
+  dir_fdes = SCM_FPORT_FDES (dir);
+
+  STRING_SYSCALL (path, c_path,
+                  fd = openat_or_openat64 (dir_fdes, c_path, iflags, imode));
+  scm_remember_upto_here_1 (dir);
+  if (fd == -1)
+    SCM_SYSERROR;
+  return scm_from_int (fd);
+}
+#undef FUNC_NAME
+#endif /* HAVE_OPENAT */
+
+/* A helper function for converting some open flags to
+   what scm_fdes_to_port expects. */
+static char *
+flags_to_mode (int iflags)
+{
+  if ((iflags & O_RDWR) == O_RDWR)
+    {
+      /* Opened read-write.  */
+      if (iflags & O_APPEND)
+	return "a+";
+      else if (iflags & O_CREAT)
+	return "w+";
+      else
+	return "r+";
+    }
+  else
+    {
+      /* Opened read-only or write-only.  */
+      if (iflags & O_APPEND)
+	return "a";
+      else if (iflags & O_WRONLY)
+	return "w";
+      else
+	return "r";
+    }
+}
+
 SCM_DEFINE (scm_open, "open", 2, 1, 0, 
             (SCM path, SCM flags, SCM mode),
 	    "Open the file named by @var{path} for reading and/or writing.\n"
@@ -285,31 +339,33 @@ SCM_DEFINE (scm_open, "open", 2, 1, 0,
   fd = scm_to_int (scm_open_fdes (path, flags, mode));
   iflags = SCM_NUM2INT (2, flags);
 
-  if ((iflags & O_RDWR) == O_RDWR)
-    {
-      /* Opened read-write.  */
-      if (iflags & O_APPEND)
-	port_mode = "a+";
-      else if (iflags & O_CREAT)
-	port_mode = "w+";
-      else
-	port_mode = "r+";
-    }
-  else
-    {
-      /* Opened read-only or write-only.  */
-      if (iflags & O_APPEND)
-	port_mode = "a";
-      else if (iflags & O_WRONLY)
-	port_mode = "w";
-      else
-	port_mode = "r";
-    }
+  port_mode = (char *) flags_to_mode (iflags);
+  newpt = scm_fdes_to_port (fd, port_mode, path);
+  return newpt;
+}
+#undef FUNC_NAME
 
+#ifdef HAVE_OPENAT
+SCM_DEFINE (scm_openat, "openat", 3, 1, 0,
+            (SCM dir, SCM path, SCM flags, SCM mode),
+            "Similar to @code{open}, but resolve the file name @var{path}\n"
+            "relative to the directory referred to by the file port @var{dir}\n"
+            "instead.")
+#define FUNC_NAME s_scm_openat
+{
+  SCM newpt;
+  char *port_mode;
+  int fd;
+  int iflags;
+
+  iflags = SCM_NUM2INT (2, flags);
+  port_mode = (char *) flags_to_mode (iflags);
+  fd = scm_to_int (scm_open_fdes_at (dir, path, flags, mode));
   newpt = scm_fdes_to_port (fd, port_mode, path);
   return newpt;
 }
 #undef FUNC_NAME
+#endif /* HAVE_OPENAT */
 
 SCM_DEFINE (scm_close, "close", 1, 0, 0, 
             (SCM fd_or_port),
diff --git a/libguile/filesys.h b/libguile/filesys.h
index 8af0f989a..1ce50d30e 100644
--- a/libguile/filesys.h
+++ b/libguile/filesys.h
@@ -44,7 +44,9 @@ SCM_API SCM scm_chmod (SCM object, SCM mode);
 SCM_API SCM scm_chmodat (SCM dir, SCM pathname, SCM mode, SCM flags);
 SCM_API SCM scm_umask (SCM mode);
 SCM_API SCM scm_open_fdes (SCM path, SCM flags, SCM mode);
+SCM_API SCM scm_open_fdes_at (SCM dir, SCM path, SCM flags, SCM mode);
 SCM_API SCM scm_open (SCM path, SCM flags, SCM mode);
+SCM_API SCM scm_openat (SCM dir, SCM path, SCM flags, SCM mode);
 SCM_API SCM scm_close (SCM fd_or_port);
 SCM_API SCM scm_close_fdes (SCM fd);
 SCM_API SCM scm_stat (SCM object, SCM exception_on_error);
diff --git a/libguile/syscalls.h b/libguile/syscalls.h
index 37d532e60..6f4061138 100644
--- a/libguile/syscalls.h
+++ b/libguile/syscalls.h
@@ -58,6 +58,7 @@
 #define lstat_or_lstat64                CHOOSE_LARGEFILE(lstat,lstat64)
 #define off_t_or_off64_t                CHOOSE_LARGEFILE(off_t,off64_t)
 #define open_or_open64                  CHOOSE_LARGEFILE(open,open64)
+#define openat_or_openat64              CHOOSE_LARGEFILE(openat,openat64)
 #define readdir_or_readdir64            CHOOSE_LARGEFILE(readdir,readdir64)
 #if SCM_HAVE_READDIR64_R == 1
 # define readdir_r_or_readdir64_r       CHOOSE_LARGEFILE(readdir_r,readdir64_r)
diff --git a/test-suite/tests/filesys.test b/test-suite/tests/filesys.test
index b794b07b3..45e77c823 100644
--- a/test-suite/tests/filesys.test
+++ b/test-suite/tests/filesys.test
@@ -728,3 +728,76 @@
     (skip-if-unsupported)
     (delete-file-at (call-with-port (open "." O_RDONLY) identity)
                     "irrelevant")))
+
+(with-test-prefix "openat"
+  (define (skip-if-unsupported)
+    (unless (defined? 'openat)
+      (throw 'unsupported)))
+
+  (define file (search-path %load-path "ice-9/boot-9.scm"))
+
+  (define (call-with-relatively-opened-file directory-arguments file-arguments
+                                            proc)
+    (call-with-port
+     (apply open directory-arguments)
+     (lambda (directory)
+       (call-with-port
+        (apply openat directory file-arguments)
+        (lambda (port)
+          (proc port))))))
+
+  (pass-if-equal "mode read-only" "r"
+    (skip-if-unsupported)
+    (call-with-relatively-opened-file
+     (list (dirname file) O_RDONLY)
+     (list (basename file) O_RDONLY)
+     (lambda (port) (port-mode port))))
+
+  (pass-if-equal "port-revealed count" 0
+    (skip-if-unsupported)
+    (call-with-relatively-opened-file
+     (list (dirname file) O_RDONLY)
+     (list (basename file) O_RDONLY)
+     (lambda (port) (port-revealed port))))
+
+  (when (file-exists? (test-file))
+    (delete-file (test-file)))
+
+  (pass-if-equal "O_CREAT/O_WRONLY" (list #t (logand (lognot (umask)) #o666) "w")
+    (skip-if-unsupported)
+    (call-with-relatively-opened-file
+     (list (dirname (test-file)) O_RDONLY)
+     (list (basename (test-file)) (logior O_WRONLY O_CREAT))
+     (lambda (port)
+       (list (file-exists? (test-file))
+             (stat:perms (stat (test-file)))
+             (port-mode port)))))
+
+  (when (file-exists? (test-file))
+    (delete-file (test-file)))
+
+  (pass-if-equal "O_CREAT/O_WRONLY, non-default mode"
+      (list #t (logand (lognot (umask)) #o700) "w")
+    (skip-if-unsupported)
+    (call-with-relatively-opened-file
+     (list (dirname (test-file)) O_RDONLY)
+     (list (basename (test-file)) (logior O_WRONLY O_CREAT) #o700)
+     (lambda (port)
+       (list (file-exists? (test-file))
+             (stat:perms (stat (test-file)))
+             (port-mode port)))))
+
+  (pass-if-exception "closed port" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (openat (call-with-port (open "." O_RDONLY) identity) "." O_RDONLY))
+
+  (pass-if-exception "non-file port" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (openat (open-input-string "") "." O_RDONLY))
+
+  (pass-if-exception "not a port" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (openat "not a port" "." O_RDONLY))
+
+  (when (file-exists? (test-file))
+    (delete-file (test-file))))
-- 
2.30.2



debug log:

solving 6f9c2c5b4e ...
found 6f9c2c5b4e in https://yhetil.org/guix/20220320215031.306710-1-maximedevos@telenet.be/ ||
	https://yhetil.org/guix/4f4d275b86619feeb257b06c645395a92312608b.camel@telenet.be/

applying [1/1] https://yhetil.org/guix/20220320215031.306710-1-maximedevos@telenet.be/
diff --git a/gnu/packages/patches/guile-openat-and-friends-13.patch b/gnu/packages/patches/guile-openat-and-friends-13.patch
new file mode 100644
index 0000000000..6f9c2c5b4e

1:59: trailing whitespace.
 
1:68: trailing whitespace.
 
1:81: trailing whitespace.
 
1:98: trailing whitespace.
 
1:153: trailing whitespace.
 SCM_DEFINE (scm_open, "open", 2, 1, 0, 
Checking patch gnu/packages/patches/guile-openat-and-friends-13.patch...
Applied patch gnu/packages/patches/guile-openat-and-friends-13.patch cleanly.
warning: squelched 7 whitespace errors
warning: 12 lines add whitespace errors.

skipping https://yhetil.org/guix/4f4d275b86619feeb257b06c645395a92312608b.camel@telenet.be/ for 6f9c2c5b4e
index at:
100644 6f9c2c5b4e4e552b91670ca2d2d35ea1707adea0	gnu/packages/patches/guile-openat-and-friends-13.patch

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.