From: Paul Eggert Date: Wed, 13 Apr 2022 06:56:41 +0000 (-0700) Subject: cp,mv,install: modularize targetdir X-Git-Tag: v9.1~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30c932a3098146128acfd839589f308ec1bb116d;p=thirdparty%2Fcoreutils.git cp,mv,install: modularize targetdir 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. --- diff --git a/bootstrap.conf b/bootstrap.conf index c1399e30c2..756df00f68 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -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 index 0000000000..79d888887c --- /dev/null +++ b/gl/lib/targetdir.c @@ -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 . */ + +#include + +#define TARGETDIR_INLINE _GL_EXTERN_INLINE +#include + +#include + +#include +#include +#include +#include + +#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 index 0000000000..be34d49813 --- /dev/null +++ b/gl/lib/targetdir.h @@ -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 . */ + +#include +#include + +#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 index 0000000000..25ccfb8998 --- /dev/null +++ b/gl/modules/targetdir @@ -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 diff --git a/src/cp.c b/src/cp.c index b2a20b9004..7d69db928a 100644 --- 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" diff --git a/src/install.c b/src/install.c index 079ce1f70a..4b06f96398 100644 --- a/src/install.c +++ b/src/install.c @@ -42,6 +42,7 @@ #include "savewd.h" #include "selinux.h" #include "stat-time.h" +#include "targetdir.h" #include "utimens.h" #include "xstrtol.h" diff --git a/src/mv.c b/src/mv.c index 21018a0d33..cb10713d71 100644 --- 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). */ diff --git a/src/system.h b/src/system.h index 768c3a1f2a..0c5c9b9009 100644 --- a/src/system.h +++ b/src/system.h @@ -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 #ifndef _D_EXACT_NAMLEN # define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)