blob: dec1b3acc476ab3204c622af78959de5cb78f43e [file] [log] [blame]
/*
* 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;
}