]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp,mv,install: modularize targetdir
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 13 Apr 2022 06:56:41 +0000 (23:56 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 13 Apr 2022 06:57:15 +0000 (23:57 -0700)
Move target directory code out of system.h to a new targetdir module.
This doesn’t change functionality.
* bootstrap.conf (gnulib_modules): Add targetdir.
* src/cp.c, src/install.c, src/mv.c: Include targetdir.h.
* src/system.h (must_be_working_directory, target_directory_operand)
(targetdir_dirfd_valid): Move from here ...
* gl/lib/targetdir.c, gl/lib/targetdir.h, gl/modules/targetdir:
... to these new files.

bootstrap.conf
gl/lib/targetdir.c [new file with mode: 0644]
gl/lib/targetdir.h [new file with mode: 0644]
gl/modules/targetdir [new file with mode: 0644]
src/cp.c
src/install.c
src/mv.c
src/system.h

index c1399e30c29a0a84f1fe3e47568b31115f46ff93..756df00f680a46377a2dae48560cc931b0fc970c 100644 (file)
@@ -262,6 +262,7 @@ gnulib_modules="
   sys_resource
   sys_stat
   sys_wait
+  targetdir
   tempname
   termios
   time_rz
diff --git a/gl/lib/targetdir.c b/gl/lib/targetdir.c
new file mode 100644 (file)
index 0000000..79d8888
--- /dev/null
@@ -0,0 +1,100 @@
+/* Target directory operands for coreutils
+
+   Copyright 2004-2022 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#define TARGETDIR_INLINE _GL_EXTERN_INLINE
+#include <targetdir.h>
+
+#include <attribute.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef O_PATH
+enum { O_PATHSEARCH = O_PATH };
+#else
+enum { O_PATHSEARCH = O_SEARCH };
+#endif
+
+/* Must F designate the working directory?  */
+
+ATTRIBUTE_PURE static inline bool
+must_be_working_directory (char const *f)
+{
+  /* Return true for ".", "./.", ".///./", etc.  */
+  while (*f++ == '.')
+    {
+      if (*f != '/')
+        return !*f;
+      while (*++f == '/')
+        continue;
+      if (!*f)
+        return true;
+    }
+  return false;
+}
+
+/* Return a file descriptor open to FILE, for use in openat.
+   As an optimization, return AT_FDCWD if FILE must be the working directory.
+   Fail and set errno if FILE is not a directory.
+   On failure return -2 if AT_FDCWD is -1, -1 otherwise.  */
+
+int
+target_directory_operand (char const *file)
+{
+  if (must_be_working_directory (file))
+    return AT_FDCWD;
+
+  int fd = -1;
+  int maybe_dir = -1;
+  struct stat st;
+
+  /* On old systems without O_DIRECTORY, like Solaris 10,
+     check with stat first lest we try to open a fifo for example and hang.
+     Also check on systems with O_PATHSEARCH == O_SEARCH, like Solaris 11,
+     where open() was seen to return EACCES for non executable non dirs.
+     */
+  if ((!O_DIRECTORY || (O_PATHSEARCH == O_SEARCH))
+      && stat (file, &st) == 0)
+    {
+      maybe_dir = S_ISDIR (st.st_mode);
+      if (! maybe_dir)
+        errno = ENOTDIR;
+    }
+
+  if (maybe_dir)
+    fd = open (file, O_PATHSEARCH | O_DIRECTORY);
+
+  if (!O_DIRECTORY && 0 <= fd)
+    {
+      /* On old systems like Solaris 10 double check type,
+         to ensure we've opened a directory.  */
+      int err;
+      if (fstat (fd, &st) != 0 ? (err = errno, true)
+          : !S_ISDIR (st.st_mode) && (err = ENOTDIR, true))
+        {
+          close (fd);
+          errno = err;
+          fd = -1;
+        }
+    }
+
+  return fd - (AT_FDCWD == -1 && fd < 0);
+}
diff --git a/gl/lib/targetdir.h b/gl/lib/targetdir.h
new file mode 100644 (file)
index 0000000..be34d49
--- /dev/null
@@ -0,0 +1,42 @@
+/* Target directory operands for coreutils
+
+   Copyright 2022 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <stdbool.h>
+
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef TARGETDIR_INLINE
+# define TARGETDIR_INLINE _GL_INLINE
+#endif
+
+/* Return a file descriptor open to FILE, for use in openat.
+   As an optimization, return AT_FDCWD if FILE must be the working directory.
+   Fail and set errno if FILE is not a directory.
+   On failure return -2 if AT_FDCWD is -1, -1 otherwise.  */
+extern int target_directory_operand (char const *file);
+
+/* Return true if FD represents success for target_directory_operand.  */
+TARGETDIR_INLINE _GL_ATTRIBUTE_PURE bool
+target_dirfd_valid (int fd)
+{
+  return fd != -1 - (AT_FDCWD == -1);
+}
+
+_GL_INLINE_HEADER_END
diff --git a/gl/modules/targetdir b/gl/modules/targetdir
new file mode 100644 (file)
index 0000000..25ccfb8
--- /dev/null
@@ -0,0 +1,25 @@
+Description:
+Target directory operands
+
+Files:
+lib/targetdir.c
+lib/targetdir.h
+
+Depends-on:
+attribute
+fcntl-h
+stdbool
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += targetdir.c targetdir.h
+
+Include:
+"targetdir.h"
+
+License:
+GPL
+
+Maintainer:
+all
index b2a20b9004b6b79b64bba0378ca38d757e17cdcb..7d69db928afca67881a7a705d976864993a4ea0c 100644 (file)
--- a/src/cp.c
+++ b/src/cp.c
@@ -33,6 +33,7 @@
 #include "ignore-value.h"
 #include "quote.h"
 #include "stat-time.h"
+#include "targetdir.h"
 #include "utimens.h"
 #include "acl.h"
 
index 079ce1f70a38dd93791db429526cb047e77f805b..4b06f96398f8ba706652e34dc457d648d22462ba 100644 (file)
@@ -42,6 +42,7 @@
 #include "savewd.h"
 #include "selinux.h"
 #include "stat-time.h"
+#include "targetdir.h"
 #include "utimens.h"
 #include "xstrtol.h"
 
index 21018a0d338ef6ebc665ad0d5a1b9b4e2df3c933..cb10713d71ab5228bcb59d3b630863ec9837fb07 100644 (file)
--- a/src/mv.c
+++ b/src/mv.c
@@ -33,6 +33,7 @@
 #include "remove.h"
 #include "renameatu.h"
 #include "root-dev-ino.h"
+#include "targetdir.h"
 #include "priv-set.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
index 768c3a1f2a45fdff3d6ace3aa87ad35a7fccc3b7..0c5c9b9009abf3a30201b7f136fc0f14d25239a1 100644 (file)
@@ -107,80 +107,6 @@ enum { O_PATHSEARCH = O_PATH };
 enum { O_PATHSEARCH = O_SEARCH };
 #endif
 
-/* Must F designate the working directory?  */
-
-ATTRIBUTE_PURE static inline bool
-must_be_working_directory (char const *f)
-{
-  /* Return true for ".", "./.", ".///./", etc.  */
-  while (*f++ == '.')
-    {
-      if (*f != '/')
-        return !*f;
-      while (*++f == '/')
-        continue;
-      if (!*f)
-        return true;
-    }
-  return false;
-}
-
-/* Return a file descriptor open to FILE, for use in openat.
-   As an optimization, return AT_FDCWD if FILE must be the working directory.
-   Fail if FILE is not a directory.
-   On failure return a negative value; this is -1 unless AT_FDCWD == -1.  */
-
-static inline int
-target_directory_operand (char const *file)
-{
-  if (must_be_working_directory (file))
-    return AT_FDCWD;
-
-  int fd = -1;
-  int maybe_dir = -1;
-  struct stat st;
-
-  /* On old systems without O_DIRECTORY, like Solaris 10,
-     check with stat first lest we try to open a fifo for example and hang.
-     Also check on systems with O_PATHSEARCH == O_SEARCH, like Solaris 11,
-     where open() was seen to return EACCES for non executable non dirs.
-     */
-  if ((!O_DIRECTORY || (O_PATHSEARCH == O_SEARCH))
-      && stat (file, &st) == 0)
-    {
-      maybe_dir = S_ISDIR (st.st_mode);
-      if (! maybe_dir)
-        errno = ENOTDIR;
-    }
-
-  if (maybe_dir)
-    fd = open (file, O_PATHSEARCH | O_DIRECTORY);
-
-  if (!O_DIRECTORY && 0 <= fd)
-    {
-      /* On old systems like Solaris 10 double check type,
-         to ensure we've opened a directory.  */
-      int err;
-      if (fstat (fd, &st) != 0 ? (err = errno, true)
-          : !S_ISDIR (st.st_mode) && (err = ENOTDIR, true))
-        {
-          close (fd);
-          errno = err;
-          fd = -1;
-        }
-    }
-
-  return fd - (AT_FDCWD == -1 && fd < 0);
-}
-
-/* Return true if FD represents success for target_directory_operand.  */
-
-static inline bool
-target_dirfd_valid (int fd)
-{
-  return fd != -1 - (AT_FDCWD == -1);
-}
-
 #include <dirent.h>
 #ifndef _D_EXACT_NAMLEN
 # define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)