1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-09-01 02:34:55 +00:00

chmod: New module.

* lib/sys_stat.in.h (chmod): Declare when GNULIB_CHMOD is 1.
* lib/chmod.c: New file, based on lib/lchmod.c.
* m4/chmod.m4: New file, based on m4/fchmodat.m4.
* m4/sys_stat_h.m4 (gl_SYS_STAT_H): Test whether chmod is declared.
(gl_SYS_STAT_H_REQUIRE_DEFAULTS): Initialize GNULIB_CHMOD.
(gl_SYS_STAT_H_DEFAULTS): Initialize REPLACE_CHMOD.
* modules/sys_stat (Makefile.am): Substitute GNULIB_CHMOD,
REPLACE_CHMOD.
* modules/chmod: New file, based on modules/lchmod.
* doc/posix-functions/chmod.texi: Mention the new module and the
problems on IRIX and Windows.
This commit is contained in:
Bruno Haible
2022-06-22 01:43:52 +02:00
parent e67a519439
commit 2f1bb5913e
8 changed files with 222 additions and 9 deletions
+15
View File
@@ -1,3 +1,18 @@
2022-06-22 Bruno Haible <bruno@clisp.org>
chmod: New module.
* lib/sys_stat.in.h (chmod): Declare when GNULIB_CHMOD is 1.
* lib/chmod.c: New file, based on lib/lchmod.c.
* m4/chmod.m4: New file, based on m4/fchmodat.m4.
* m4/sys_stat_h.m4 (gl_SYS_STAT_H): Test whether chmod is declared.
(gl_SYS_STAT_H_REQUIRE_DEFAULTS): Initialize GNULIB_CHMOD.
(gl_SYS_STAT_H_DEFAULTS): Initialize REPLACE_CHMOD.
* modules/sys_stat (Makefile.am): Substitute GNULIB_CHMOD,
REPLACE_CHMOD.
* modules/chmod: New file, based on modules/lchmod.
* doc/posix-functions/chmod.texi: Mention the new module and the
problems on IRIX and Windows.
2022-06-21 Bruno Haible <bruno@clisp.org>
lchmod: Simplify.
+11 -6
View File
@@ -4,16 +4,21 @@
POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html}
Gnulib module: ---
Gnulib module: chmod
Portability problems fixed by Gnulib:
@itemize
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
This function does not fail when the file name argument ends in a slash
and (without the slash) names a non-directory, on some platforms:
AIX 7.2.
AIX 7.2, IRIX 6.5.
@item
This function fails with a wrong error code (EINVAL instead of ENOTDIR)
when the file name argument ends in a slash and (without the slash) names
a non-directory, on some platforms:
mingw, MSVC.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@end itemize
+47
View File
@@ -0,0 +1,47 @@
/* Implement chmod on platforms where it does not work correctly.
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 <config.h>
/* Specification. */
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
int
rpl_chmod (const char *filename, mode_t mode)
#undef chmod
#if defined _WIN32 && !defined __CYGWIN__
# define chmod _chmod
#endif
{
size_t len = strlen (filename);
if (len > 0 && filename[len - 1] == '/')
{
struct stat st;
if (lstat (filename, &st) < 0)
return -1;
if (!S_ISDIR (st.st_mode))
{
errno = ENOTDIR;
return -1;
}
}
return chmod (filename, mode);
}
+27 -1
View File
@@ -391,7 +391,33 @@ struct stat
#endif
#if @GNULIB_MDA_CHMOD@
#if @GNULIB_CHMOD@
# if @REPLACE_CHMOD@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef chmod
# define chmod rpl_chmod
# endif
_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode));
# elif defined _WIN32 && !defined __CYGWIN__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef chmod
# define chmod _chmod
# endif
/* Need to cast, because in mingw the last argument is 'int mode'. */
_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode));
# else
_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode));
# endif
_GL_CXXALIASWARN (chmod);
#elif defined GNULIB_POSIXCHECK
# undef chmod
# if HAVE_RAW_DECL_CHMOD
_GL_WARN_ON_USE (chmod, "chmod has portability problems - "
"use gnulib module chmod for portability");
# endif
#elif @GNULIB_MDA_CHMOD@
/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not
required. In C++ with GNULIB_NAMESPACE, avoid differences between
platforms by defining GNULIB_NAMESPACE::chmod always. */
+84
View File
@@ -0,0 +1,84 @@
# chmod.m4 serial 1
dnl Copyright (C) 2004-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
AC_DEFUN([gl_FUNC_CHMOD],
[
AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
AC_CACHE_CHECK([whether chmod works],
[gl_cv_func_chmod_works],
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[
AC_INCLUDES_DEFAULT[
#if defined _WIN32 && !defined __CYGWIN__
#include <io.h>
#endif
#include <errno.h>
#include <fcntl.h>
#ifndef S_IRUSR
#define S_IRUSR 0400
#endif
#ifndef S_IWUSR
#define S_IWUSR 0200
#endif
#ifndef S_IRWXU
#define S_IRWXU 0700
#endif
#ifndef S_IRWXG
#define S_IRWXG 0070
#endif
#ifndef S_IRWXO
#define S_IRWXO 0007
#endif
]GL_MDA_DEFINES],
[[
int permissive = S_IRWXU | S_IRWXG | S_IRWXO;
int desired = S_IRUSR | S_IWUSR;
int result = 0;
#define file "conftest.chmod"
if (open (file, O_CREAT | O_WRONLY | O_TRUNC, permissive) < 0)
return 1;
/* Test whether chmod rejects a trailing slash on a non-directory,
with error ENOTDIR.
This test fails on AIX 7.2, IRIX 6.5 (no error) and
native Windows (error EINVAL). */
errno = 0;
if (chmod (file "/", desired) == 0)
result |= 2;
else if (errno != ENOTDIR)
result |= 4;
return result;
]])],
[gl_cv_func_chmod_works=yes],
[gl_cv_func_chmod_works=no],
[case "$host_os" in
# Guess no on AIX, IRIX, native Windows.
aix* | irix* | mingw*)
gl_cv_func_chmod_works="guessing no" ;;
# Guess yes on glibc, musl libc, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Haiku, Cygwin.
*-gnu* | gnu* | *-musl* | darwin* | freebsd* | midnightbsd* | netbsd* | openbsd* | solaris* | haiku* | cygwin*)
gl_cv_func_chmod_works="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
*)
gl_cv_func_chmod_works="$gl_cross_guess_normal" ;;
esac
])
rm -f conftest.chmod
])
case "$gl_cv_func_chmod_works" in
*yes) ;;
*) REPLACE_CHMOD=1 ;;
esac
])
# Prerequisites of lib/chmod.c.
AC_DEFUN([gl_PREREQ_CHMOD],
[
:
])
+4 -2
View File
@@ -1,4 +1,4 @@
# sys_stat_h.m4 serial 41 -*- Autoconf -*-
# sys_stat_h.m4 serial 42 -*- Autoconf -*-
dnl Copyright (C) 2006-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -46,7 +46,7 @@ AC_DEFUN_ONCE([gl_SYS_STAT_H],
dnl Check for declarations of anything we want to poison if the
dnl corresponding gnulib module is not in use.
gl_WARN_ON_USE_PREPARE([[#include <sys/stat.h>
]], [fchmodat fstat fstatat futimens getumask lchmod lstat
]], [chmod fchmodat fstat fstatat futimens getumask lchmod lstat
mkdirat mkfifo mkfifoat mknod mknodat stat utimensat])
AC_REQUIRE([AC_C_RESTRICT])
@@ -72,6 +72,7 @@ AC_DEFUN([gl_SYS_STAT_H_REQUIRE_DEFAULTS],
[
m4_defun(GL_MODULE_INDICATOR_PREFIX[_SYS_STAT_H_MODULE_INDICATOR_DEFAULTS], [
gl_UNISTD_H_REQUIRE_DEFAULTS dnl for REPLACE_FCHDIR
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CHMOD])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FCHMODAT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTAT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTATAT])
@@ -112,6 +113,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
HAVE_MKNOD=1; AC_SUBST([HAVE_MKNOD])
HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT])
HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT])
REPLACE_CHMOD=0; AC_SUBST([REPLACE_CHMOD])
REPLACE_FCHMODAT=0; AC_SUBST([REPLACE_FCHMODAT])
REPLACE_FSTAT=0; AC_SUBST([REPLACE_FSTAT])
REPLACE_FSTATAT=0; AC_SUBST([REPLACE_FSTATAT])
+32
View File
@@ -0,0 +1,32 @@
Description:
chmod() function: change the permissions of a file
Files:
lib/chmod.c
m4/chmod.m4
Depends-on:
sys_stat
lstat [test $REPLACE_CHMOD = 1]
configure.ac:
gl_FUNC_CHMOD
gl_CONDITIONAL([GL_COND_OBJ_CHMOD], [test $REPLACE_CHMOD = 1])
AM_COND_IF([GL_COND_OBJ_CHMOD], [
gl_PREREQ_CHMOD
])
gl_SYS_STAT_MODULE_INDICATOR([chmod])
Makefile.am:
if GL_COND_OBJ_CHMOD
lib_SOURCES += chmod.c
endif
Include:
<sys/stat.h>
License:
GPL
Maintainer:
Paul Eggert, Bruno Haible
+2
View File
@@ -36,6 +36,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
-e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
-e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \
-e 's/@''GNULIB_CHMOD''@/$(GNULIB_CHMOD)/g' \
-e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
-e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
-e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
@@ -67,6 +68,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \
-e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
-e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
-e 's|@''REPLACE_CHMOD''@|$(REPLACE_CHMOD)|g' \
-e 's|@''REPLACE_FCHMODAT''@|$(REPLACE_FCHMODAT)|g' \
-e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \
-e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \