/* Implementation of the CHMOD intrinsic.
- Copyright (C) 2006, 2007, 2009, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2006-2015 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
This file is part of the GNU Fortran runtime library (libgfortran).
#if defined(HAVE_SYS_STAT_H)
-#include <stdbool.h>
#include <string.h> /* For memcpy. */
+#include <stdlib.h> /* For free. */
#include <sys/stat.h> /* For stat, chmod and umask. */
A return value of 0 indicates success, -1 an error of chmod() while 1
indicates a mode parsing error. */
-extern int chmod_func (char *, char *, gfc_charlen_type, gfc_charlen_type);
-export_proto(chmod_func);
-int
-chmod_func (char *name, char *mode, gfc_charlen_type name_len,
- gfc_charlen_type mode_len)
+static int
+chmod_internal (char *file, char *mode, gfc_charlen_type mode_len)
{
- char * file;
int i;
bool ugo[3];
bool rwxXstugo[9];
int set_mode, part;
- bool is_dir, honor_umask, continue_clause = false;
+ bool honor_umask, continue_clause = false;
+#ifndef __MINGW32__
+ bool is_dir;
+#endif
mode_t mode_mask, file_mode, new_mode;
struct stat stat_buf;
- /* Trim trailing spaces of the file name. */
- while (name_len > 0 && name[name_len - 1] == ' ')
- name_len--;
-
- /* Make a null terminated copy of the file name. */
- file = gfc_alloca (name_len + 1);
- memcpy (file, name, name_len);
- file[name_len] = '\0';
-
if (mode_len == 0)
return 1;
if (mode[0] >= '0' && mode[0] <= '9')
{
#ifdef __MINGW32__
- unsigned mode;
- if (sscanf (mode, "%o", &mode) != 1)
+ unsigned fmode;
+ if (sscanf (mode, "%o", &fmode) != 1)
return 1;
- file_mode = (mode_t) mode;
+ file_mode = (mode_t) fmode;
#else
if (sscanf (mode, "%o", &file_mode) != 1)
return 1;
return 1;
file_mode = stat_buf.st_mode & ~S_IFMT;
+#ifndef __MINGW32__
is_dir = stat_buf.st_mode & S_IFDIR;
+#endif
#ifdef HAVE_UMASK
/* Obtain the umask without distroying the setting. */
if ((ugo[2] || honor_umask) && !rwxXstugo[8])
file_mode = (file_mode & ~(S_IROTH | S_IWOTH | S_IXOTH))
| (new_mode & (S_IROTH | S_IWOTH | S_IXOTH));
+#ifndef __VXWORKS__
if (is_dir && rwxXstugo[5])
file_mode |= S_ISVTX;
else if (!is_dir)
file_mode &= ~S_ISVTX;
+#endif
#endif
}
else if (set_mode == 2)
{
/* Clear '-'. */
file_mode &= ~new_mode;
-#ifndef __MINGW32__
+#if !defined( __MINGW32__) && !defined (__VXWORKS__)
if (rwxXstugo[5] || !is_dir)
file_mode &= ~S_ISVTX;
#endif
else if (set_mode == 3)
{
file_mode |= new_mode;
-#ifndef __MINGW32__
+#if !defined (__MINGW32__) && !defined (__VXWORKS__)
if (rwxXstugo[5] && is_dir)
file_mode |= S_ISVTX;
else if (!is_dir)
}
+extern int chmod_func (char *, char *, gfc_charlen_type, gfc_charlen_type);
+export_proto(chmod_func);
+
+int
+chmod_func (char *name, char *mode, gfc_charlen_type name_len,
+ gfc_charlen_type mode_len)
+{
+ char *cname = fc_strdup (name, name_len);
+ int ret = chmod_internal (cname, mode, mode_len);
+ free (cname);
+ return ret;
+}
+
+
extern void chmod_i4_sub (char *, char *, GFC_INTEGER_4 *,
gfc_charlen_type, gfc_charlen_type);
export_proto(chmod_i4_sub);