| /* |
| * R : A Computer Language for Statistical Data Analysis |
| * Copyright (C) 1998--2015 The R Core Team |
| * |
| * 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 2 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, a copy is available at |
| * https://www.R-project.org/Licenses/ |
| */ |
| |
| /* Formerly in src/main/platform.c */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include <config.h> |
| #endif |
| |
| #include <Defn.h> |
| #undef _ |
| #ifdef ENABLE_NLS |
| #include <libintl.h> |
| #define _(String) dgettext ("tools", String) |
| #else |
| #define _(String) (String) |
| #endif |
| |
| #ifdef HAVE_SYS_TYPES_H |
| # include <sys/types.h> |
| #endif |
| #ifdef HAVE_SYS_STAT_H |
| # include <sys/stat.h> |
| #endif |
| |
| #if HAVE_DIRENT_H |
| # include <dirent.h> |
| #elif HAVE_SYS_NDIR_H |
| # include <sys/ndir.h> |
| #elif HAVE_SYS_DIR_H |
| # include <sys/dir.h> |
| #elif HAVE_NDIR_H |
| # include <ndir.h> |
| #endif |
| static const char * const R_FileSep = FILESEP; |
| |
| static void chmod_one(const char *name, const int grpwrt) |
| { |
| DIR *dir; |
| struct dirent *de; |
| char p[PATH_MAX]; |
| #ifdef Win32 |
| struct _stati64 sb; |
| #else |
| struct stat sb; |
| #endif |
| #ifndef Win32 |
| mode_t mask, dirmask; |
| if (grpwrt) { |
| mask = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP; /* 0664 */ |
| dirmask = mask | S_IXUSR | S_IXGRP | S_IXOTH; /* 0755 */ |
| } else { |
| mask = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR; /* 0644 */ |
| dirmask = mask | S_IXUSR | S_IXGRP | S_IXOTH; /* 0755 */ |
| } |
| #endif |
| |
| if (streql(name, ".") || streql(name, "..")) return; |
| if (!R_FileExists(name)) return; |
| #ifdef Win32 |
| _stati64(name, &sb); |
| chmod(name, _S_IWRITE); |
| #else |
| stat(name, &sb); |
| chmod(name, (sb.st_mode | mask) & dirmask); |
| #endif |
| if ((sb.st_mode & S_IFDIR) > 0) { /* a directory */ |
| #ifndef Win32 |
| chmod(name, dirmask); |
| #endif |
| if ((dir = opendir(name)) != NULL) { |
| while ((de = readdir(dir))) { |
| if (streql(de->d_name, ".") || streql(de->d_name, "..")) |
| continue; |
| size_t n = strlen(name); |
| if (name[n-1] == R_FileSep[0]) |
| snprintf(p, PATH_MAX, "%s%s", name, de->d_name); |
| else |
| snprintf(p, PATH_MAX, "%s%s%s", name, R_FileSep, de->d_name); |
| chmod_one(p, grpwrt); |
| } |
| closedir(dir); |
| } else { |
| /* we were unable to read a dir */ |
| } |
| } |
| } |
| |
| /* recursively fix up permissions: used for R CMD INSTALL and build. |
| 'gwsxp' means set group-write permissions on directories. |
| NB: this overrides umask. */ |
| /* This is a .Call so manages R_alloc stack */ |
| SEXP dirchmod(SEXP dr, SEXP gwsxp) |
| { |
| if(!isString(dr) || LENGTH(dr) != 1) |
| error(_("invalid '%s' argument"), "dir"); |
| chmod_one(translateChar(STRING_ELT(dr, 0)), asLogical(gwsxp)); |
| |
| return R_NilValue; |
| } |
| |
| #if defined(BUFSIZ) && (BUFSIZ > 512) |
| /* OS's buffer size in stdio.h, probably. |
| Windows has 512, Solaris 1024, glibc 8192 |
| */ |
| # define APPENDBUFSIZE BUFSIZ |
| #else |
| # define APPENDBUFSIZE 512 |
| #endif |
| |
| SEXP codeFilesAppend(SEXP f1, SEXP f2) |
| { |
| int n, n1, n2; |
| if (!isString(f1) || (n1 = LENGTH(f1)) != 1) |
| error(_("invalid '%s' argument"), "file1"); |
| if (!isString(f2)) |
| error(_("invalid '%s' argument"), "file2"); |
| n2 = LENGTH(f2); |
| if (n2 < 1) return allocVector(LGLSXP, 0); |
| n = (n1 > n2) ? n1 : n2; // will be n2. |
| SEXP ans = PROTECT(allocVector(LGLSXP, n)); |
| for (int i = 0; i < n; i++) LOGICAL(ans)[i] = 0; /* all FALSE */ |
| FILE *fp1, *fp2; |
| char buf[APPENDBUFSIZE]; |
| int status = 0; |
| size_t nchar; |
| if (STRING_ELT(f1, 0) == NA_STRING || |
| !(fp1 = RC_fopen(STRING_ELT(f1, 0), "ab", TRUE))) |
| goto done; |
| for (int i = 0; i < n; i++) { |
| status = 0; |
| if (STRING_ELT(f2, i) == NA_STRING || |
| !(fp2 = RC_fopen(STRING_ELT(f2, i), "rb", TRUE))) continue; |
| snprintf(buf, APPENDBUFSIZE, "#line 1 \"%s\"\n", |
| CHAR(STRING_ELT(f2, i))); |
| if(fwrite(buf, 1, strlen(buf), fp1) != strlen(buf)) goto append_error; |
| while ((nchar = fread(buf, 1, APPENDBUFSIZE, fp2)) == APPENDBUFSIZE) |
| if (fwrite(buf, 1, APPENDBUFSIZE, fp1) != APPENDBUFSIZE) |
| goto append_error; |
| if (fwrite(buf, 1, nchar, fp1) != nchar) goto append_error; |
| if (!nchar || buf[nchar - 1] != '\n') |
| if (fwrite("\n", 1, 1, fp1) != 1) goto append_error; |
| |
| status = 1; |
| append_error: |
| if (status == 0) warning(_("write error during file append")); |
| LOGICAL(ans)[i] = status; |
| fclose(fp2); |
| } |
| fclose(fp1); |
| done: |
| UNPROTECT(1); |
| return ans; |
| } |