all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob e922b0aeb5d22900dd0b942d23fc1132ee8735fb 9687 bytes (raw)
name: gnu/packages/patches/guile-openat-and-friends-08.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
 
Guix-Upstream: https://lists.gnu.org/archive/html/guile-devel/2021-11/msg00005.html
From: Maxime Devos <maximedevos@telenet.be>
Subject: [PATCH v2 08/14] =?UTF-8?q?Define=20a=20Scheme=20binding=20to=20?=
 =?UTF-8?q?=E2=80=98renameat=E2=80=99=20when=20it=20exists.?=
Date: Tue, 16 Nov 2021 11:06:31 +0000
Message-Id: <20211116110637.125579-9-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 ‘renameat’ is defined.
* libguile/filesys.c (scm_renameat): Define a Scheme binding
  to the ‘renameat’ system call.
* doc/ref/posix.texi (File System): Document it.
* libguile/filesys.h (scm_renameat): Make it part of the C API.
* test-suite/tests/filesys.test ("rename-file-at"): New tests.
---
 configure.ac                  |   2 +-
 doc/ref/posix.texi            |   9 +++
 libguile/filesys.c            |  34 +++++++++++
 libguile/filesys.h            |   1 +
 test-suite/tests/filesys.test | 104 ++++++++++++++++++++++++++++++++++
 5 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index da8dfadd0..e67892feb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -485,7 +485,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
 #
 AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid         \
   fesetround ftime ftruncate fchown fchmod fchdir readlinkat		\
-  symlinkat mkdirat getcwd geteuid getsid				\
+  symlinkat mkdirat renameat getcwd geteuid getsid				\
   gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mkdtemp mknod   \
   nice readlink rename rmdir setegid seteuid                            \
   setlocale setuid setgid setpgid setsid sigaction siginterrupt stat64  \
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index 7f136376b..ebb001581 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -877,6 +877,15 @@ Renames the file specified by @var{oldname} to @var{newname}.
 The return value is unspecified.
 @end deffn
 
+@findex renameat
+@deffn {Scheme Procedure} rename-file-at olddir oldname newdir newname
+@deffnx {C Function} scm_renameat (olddir, oldname, newdir, newname)
+Like @code{rename-file}, but when @var{olddir} or @var{newdir} is true,
+resolve @var{oldname} or @var{newname} relative to the directory
+specified by the file port @var{olddir} or @var{newdir} instead of the
+current working directory.
+@end deffn
+
 @deffn {Scheme Procedure} link oldpath newpath
 @deffnx {C Function} scm_link (oldpath, newpath)
 Creates a new name @var{newpath} in the file system for the
diff --git a/libguile/filesys.c b/libguile/filesys.c
index ee01b2e2c..9c63beaa8 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1421,6 +1421,40 @@ SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
 }
 #undef FUNC_NAME
 
+#ifdef HAVE_RENAMEAT
+SCM_DEFINE (scm_renameat, "rename-file-at", 4, 0, 0,
+            (SCM olddir, SCM oldname, SCM newdir, SCM newname),
+            "Like @code{rename-file}, but when @var{olddir} or @var{newdir}\n"
+            "is true, resolve @var{oldname} or @var{newname} relative to\n"
+            "the directory specified by file port @var{olddir} or\n"
+            "@var{newdir} instead of the current working directory.")
+#define FUNC_NAME s_scm_renameat
+{
+  int rv;
+  int old_fdes, new_fdes;
+
+  old_fdes = AT_FDCWD;
+  new_fdes = AT_FDCWD;
+
+  if (scm_is_true (olddir)) {
+    SCM_VALIDATE_OPFPORT (SCM_ARG1, olddir);
+    old_fdes = SCM_FPORT_FDES (olddir);
+  }
+  if (scm_is_true (newdir)) {
+    SCM_VALIDATE_OPFPORT (SCM_ARG3, newdir);
+    new_fdes = SCM_FPORT_FDES (newdir);
+  }
+
+  STRING2_SYSCALL (oldname, c_oldname,
+		   newname, c_newname,
+		   rv = renameat (old_fdes, c_oldname, new_fdes, c_newname));
+  scm_remember_upto_here_2 (olddir, newdir);
+  if (rv != 0)
+    SCM_SYSERROR;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif
 
 SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0, 
            (SCM str),
diff --git a/libguile/filesys.h b/libguile/filesys.h
index f0dd35ede..7e17cc585 100644
--- a/libguile/filesys.h
+++ b/libguile/filesys.h
@@ -48,6 +48,7 @@ SCM_API SCM scm_close_fdes (SCM fd);
 SCM_API SCM scm_stat (SCM object, SCM exception_on_error);
 SCM_API SCM scm_link (SCM oldpath, SCM newpath);
 SCM_API SCM scm_rename (SCM oldname, SCM newname);
+SCM_API SCM scm_renameat (SCM olddir, SCM oldname, SCM newdir, SCM newname);
 SCM_API SCM scm_delete_file (SCM str);
 SCM_API SCM scm_mkdir (SCM path, SCM mode);
 SCM_API SCM scm_mkdirat (SCM dir, SCM path, SCM mode);
diff --git a/test-suite/tests/filesys.test b/test-suite/tests/filesys.test
index 4ea62d513..bbce2c858 100644
--- a/test-suite/tests/filesys.test
+++ b/test-suite/tests/filesys.test
@@ -31,6 +31,8 @@
   (data-file-name "filesys-test-link.tmp"))
 (define (test-directory)
   (data-file-name "filesys-test-dir.tmp"))
+(define (test-directory2)
+  (data-file-name "filesys-test-dir2.tmp"))
 
 
 ;;;
@@ -432,3 +434,105 @@
        (mkdirat port (test-directory))
        (stat:perms (stat (test-directory))))))
   (maybe-delete-directory))
+
+(with-test-prefix "rename-file-at"
+  (define (skip-if-unsupported)
+    (unless (defined? 'rename-file-at)
+      (throw 'unsupported)))
+  (pass-if-equal "current working directory" '(#f "hello")
+    (skip-if-unsupported)
+    ;; Create a file in the test directory
+    (call-with-output-file "filesys-test-a.tmp"
+      (lambda (port) (display "hello" port)))
+    ;; Try to rename it
+    (rename-file-at #f "filesys-test-a.tmp" #f "filesys-test-b.tmp")
+    ;; Verify it exists under the new name, and not under the old name
+    (list (file-exists? "filesys-test-a.tmp")
+          (call-with-input-file "filesys-test-b.tmp" get-string-all)))
+
+  (false-if-exception (delete-file "filesys-test-a.tmp"))
+  (false-if-exception (delete-file "filesys-test-b.tmp"))
+
+  (pass-if-equal "two ports" '(#f "hello")
+    (skip-if-unsupported)
+    (mkdir (test-directory))
+    (mkdir (test-directory2))
+    ;; Create a file in the first directory
+    (call-with-output-file (in-vicinity (test-directory) "a")
+      (lambda (port) (display "hello" port)))
+    (let ((port1 (open (test-directory) O_RDONLY))
+          (port2 (open (test-directory2) O_RDONLY)))
+      ;; Try to rename it
+      (rename-file-at port1 "a" port2 "b")
+      (close-port port1)
+      (close-port port2)
+      ;; Verify it exists under the new name, and not under the old name
+      (list (file-exists? (in-vicinity (test-directory) "a"))
+            (call-with-input-file (in-vicinity (test-directory2) "b")
+              get-string-all))))
+  (false-if-exception (delete-file (in-vicinity (test-directory) "a")))
+  (false-if-exception (delete-file (in-vicinity (test-directory2) "b")))
+  (false-if-exception (rmdir (test-directory)))
+  (false-if-exception (rmdir (test-directory2)))
+
+  (pass-if-equal "port and current working directory" '(#f "hello")
+    (skip-if-unsupported)
+    (mkdir (test-directory))
+    ;; Create a file in (test-directory)
+    (call-with-output-file (in-vicinity (test-directory) "a")
+      (lambda (port) (display "hello" port)))
+    (let ((port (open (test-directory) O_RDONLY)))
+      ;; Try to rename it
+      (rename-file-at port "a" #f (basename (test-file)))
+      (close-port port)
+      ;; Verify it exists under the new name, and not under the old name.
+      (list (file-exists? (in-vicinity (test-directory) "a"))
+            (call-with-input-file (test-file) get-string-all))))
+  (false-if-exception (delete-file (in-vicinity (test-directory) "a")))
+  (false-if-exception (rmdir (test-directory)))
+  (false-if-exception (delete-file (test-file)))
+
+  (pass-if-equal "current working directory and port" '(#f "hello")
+    (skip-if-unsupported)
+    (mkdir (test-directory))
+    ;; Create a file in the working directory
+    (call-with-output-file (test-file)
+      (lambda (port) (display "hello" port)))
+    (let ((port (open (test-directory) O_RDONLY)))
+      ;; Try to rename it
+      (rename-file-at #f (basename (test-file)) port "b")
+      (close-port port)
+      ;; Verify it exists under the new name, and not under the old name.
+      (list (file-exists? (test-file))
+            (call-with-input-file (in-vicinity (test-directory) "b")
+              get-string-all))))
+
+  (false-if-exception (delete-file (in-vicinity (test-directory) "b")))
+  (false-if-exception (delete-file (test-file)))
+  (false-if-exception (rmdir (test-directory)))
+
+  (pass-if-exception "not a file port (1)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at (open-input-string "") "some" #f "thing"))
+
+  (pass-if-exception "not a file port (2)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at #f "some" (open-input-string "") "thing"))
+
+  (pass-if-exception "closed port (1)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at (call-with-port (open "." O_RDONLY) identity)
+                    "some" #f "thing"))
+
+  (pass-if-exception "closed port (2)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at #f "some" (call-with-port (open "." O_RDONLY) identity)
+                    "thing"))
+
+  (pass-if-exception "not a string (1)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at #f 'what #f "thing"))
+
+  (pass-if-exception "not a string (2)" exception:wrong-type-arg
+    (skip-if-unsupported)
+    (rename-file-at #f "some" #f 'what)))
-- 
2.30.2



debug log:

solving e922b0aeb5 ...
found e922b0aeb5 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-08.patch b/gnu/packages/patches/guile-openat-and-friends-08.patch
new file mode 100644
index 0000000000..e922b0aeb5

1:54: trailing whitespace.
 
1:74: trailing whitespace.
 
1:109: trailing whitespace.
 
1:110: trailing whitespace.
 SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0, 
1:134: trailing whitespace.
 
Checking patch gnu/packages/patches/guile-openat-and-friends-08.patch...
Applied patch gnu/packages/patches/guile-openat-and-friends-08.patch cleanly.
warning: squelched 3 whitespace errors
warning: 8 lines add whitespace errors.

skipping https://yhetil.org/guix/4f4d275b86619feeb257b06c645395a92312608b.camel@telenet.be/ for e922b0aeb5
index at:
100644 e922b0aeb5d22900dd0b942d23fc1132ee8735fb	gnu/packages/patches/guile-openat-and-friends-08.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.