Take better care of permissions when copying
This is now better enforced for files, fifos and directories.
This commit is contained in:
parent
6b018863a3
commit
5da4e529a2
39
src/cp.c
39
src/cp.c
|
@ -92,10 +92,11 @@ static int _cp_confirm(char const * message)
|
|||
|
||||
/* _cp_single
|
||||
* XXX TOCTOU all over the place (*stat) but seem impossible to avoid */
|
||||
static int _cp_single_dir(Prefs * prefs, char const * src, char const * dst);
|
||||
static int _cp_single_fifo(char const * dst);
|
||||
static int _cp_single_dir(Prefs * prefs, char const * src, char const * dst,
|
||||
mode_t mode);
|
||||
static int _cp_single_fifo(char const * dst, mode_t mode);
|
||||
static int _cp_single_symlink(char const * src, char const * dst);
|
||||
static int _cp_single_regular(char const * src, char const * dst);
|
||||
static int _cp_single_regular(char const * src, char const * dst, mode_t mode);
|
||||
static int _cp_single_p(char const * dst, struct stat * st);
|
||||
|
||||
static int _cp_single(Prefs * prefs, char const * src, char const * dst)
|
||||
|
@ -125,13 +126,13 @@ static int _cp_single(Prefs * prefs, char const * src, char const * dst)
|
|||
return _cp_error(dst, 1);
|
||||
}
|
||||
if(S_ISDIR(st.st_mode))
|
||||
ret = _cp_single_dir(prefs, src, dst);
|
||||
ret = _cp_single_dir(prefs, src, dst, st.st_mode & 0777);
|
||||
else if(S_ISFIFO(st.st_mode))
|
||||
ret = _cp_single_fifo(dst);
|
||||
ret = _cp_single_fifo(dst, st.st_mode & 0666);
|
||||
else if(S_ISLNK(st.st_mode))
|
||||
ret = _cp_single_symlink(src, dst);
|
||||
else
|
||||
ret = _cp_single_regular(src, dst);
|
||||
ret = _cp_single_regular(src, dst, st.st_mode & 0777);
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
if(*prefs & CP_PREFS_p) /* XXX TOCTOU */
|
||||
|
@ -140,18 +141,20 @@ static int _cp_single(Prefs * prefs, char const * src, char const * dst)
|
|||
}
|
||||
|
||||
/* single_dir */
|
||||
static int _cp_single_recurse(Prefs * prefs, char const * src,
|
||||
char const * dst);
|
||||
static int _cp_single_recurse(Prefs * prefs, char const * src, char const * dst,
|
||||
mode_t mode);
|
||||
|
||||
static int _cp_single_dir(Prefs * prefs, char const * src, char const * dst)
|
||||
static int _cp_single_dir(Prefs * prefs, char const * src, char const * dst,
|
||||
mode_t mode)
|
||||
{
|
||||
if(*prefs & CP_PREFS_R)
|
||||
return _cp_single_recurse(prefs, src, dst);
|
||||
return _cp_single_recurse(prefs, src, dst, mode);
|
||||
fprintf(stderr, "%s%s%s", "cp: ", src, ": Omitting directory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cp_single_recurse(Prefs * prefs, char const * src, char const * dst)
|
||||
static int _cp_single_recurse(Prefs * prefs, char const * src, char const * dst,
|
||||
mode_t mode)
|
||||
{
|
||||
int ret = 0;
|
||||
Prefs prefs2 = *prefs;
|
||||
|
@ -163,7 +166,7 @@ static int _cp_single_recurse(Prefs * prefs, char const * src, char const * dst)
|
|||
char * sdst = NULL;
|
||||
char * p;
|
||||
|
||||
if(mkdir(dst, 0777) != 0 && errno != EEXIST)
|
||||
if(mkdir(dst, mode) != 0 && errno != EEXIST)
|
||||
return _cp_error(dst, 1);
|
||||
srclen = strlen(src);
|
||||
dstlen = strlen(dst);
|
||||
|
@ -198,9 +201,9 @@ static int _cp_single_recurse(Prefs * prefs, char const * src, char const * dst)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int _cp_single_fifo(char const * dst)
|
||||
static int _cp_single_fifo(char const * dst, mode_t mode)
|
||||
{
|
||||
if(mkfifo(dst, 0666) != 0)
|
||||
if(mkfifo(dst, mode) != 0)
|
||||
return _cp_error(dst, 1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -218,19 +221,23 @@ static int _cp_single_symlink(char const * src, char const * dst)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _cp_single_regular(char const * src, char const * dst)
|
||||
static int _cp_single_regular(char const * src, char const * dst, mode_t mode)
|
||||
{
|
||||
int ret = 0;
|
||||
FILE * fsrc;
|
||||
int fd;
|
||||
FILE * fdst;
|
||||
char buf[BUFSIZ];
|
||||
size_t size;
|
||||
|
||||
if((fsrc = fopen(src, "r")) == NULL)
|
||||
return _cp_error(src, 1);
|
||||
if((fdst = fopen(dst, "w")) == NULL)
|
||||
if((fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0
|
||||
|| (fdst = fdopen(fd, "w")) == NULL)
|
||||
{
|
||||
ret = _cp_error(dst, 1);
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
fclose(fsrc);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user