rktio: fix Unix file copy to copy permissions

This commit is contained in:
Matthew Flatt 2017-06-18 09:31:14 -06:00
parent 60e85fcaf3
commit c1416d07d6
3 changed files with 51 additions and 4 deletions

View File

@ -3472,6 +3472,18 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
ok = 1;
}
}
if (ok) {
if (!rktio_copy_file_finish_permissions(scheme_rktio, cf)) {
rktio_copy_file_stop(scheme_rktio, cf);
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
"copy-file: cannot set destination's permissions\n"
" source path: %q\n"
" destination path: %q",
filename_for_error(argv[0]),
filename_for_error(argv[1]));
}
}
rktio_copy_file_stop(scheme_rktio, cf);
if (ok)
return scheme_void;

View File

@ -745,11 +745,25 @@ typedef struct rktio_file_copy_t rktio_file_copy_t;
RKTIO_EXTERN rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, const char *dest, const char *src,
rktio_bool_t exists_ok);
/* Can report `RKTIO_ERROR_EXISTS`. */
/* Starts a file copy. Depending on the OS, this step may perform the
whole copy, or it may just get started. Can report
`RKTIO_ERROR_EXISTS`. */
RKTIO_EXTERN int rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc);
RKTIO_EXTERN rktio_bool_t rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc);
RKTIO_EXTERN rktio_ok_t rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc);
/* As long as the copy isn't done, call `rktio_copy_file_step` to make
a little progress. Use `rktio_copy_file_finish_permissions` (optionally)
and then `rktio_copy_file_stop` when done. */
RKTIO_EXTERN rktio_ok_t rktio_copy_file_finish_permissions(rktio_t *rktio, rktio_file_copy_t *fc);
/* Depending on the OS, copies permissions from the source to the
destination. This step can be performed at any time between the
start and stop. Reports success if this step isn't needed (e.g.,
where a copy fully completes when it is started). */
RKTIO_EXTERN void rktio_copy_file_stop(rktio_t *rktio, rktio_file_copy_t *fc);
/* Deallocates the copy process, interrupting it if the copy is not
complete. */
/*************************************************/
/* System paths */

View File

@ -1509,6 +1509,9 @@ void rktio_directory_list_stop(rktio_t *rktio, rktio_directory_list_t *dl)
struct rktio_file_copy_t {
int done;
rktio_fd_t *src_fd, *dest_fd;
#ifdef RKTIO_SYSTEM_UNIX
intptr_t mode;
#endif
};
rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, const char *dest, const char *src, int exists_ok)
@ -1552,6 +1555,7 @@ rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, const char *dest, const
fc->done = 0;
fc->src_fd = src_fd;
fc->dest_fd = dest_fd;
fc->mode = buf.st_mode;
return fc;
}
@ -1583,12 +1587,12 @@ rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, const char *dest, const
#endif
}
int rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc)
rktio_bool_t rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc)
{
return fc->done;
}
int rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc)
rktio_ok_t rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc)
{
#ifdef RKTIO_SYSTEM_UNIX
char buffer[4096];
@ -1620,6 +1624,23 @@ int rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc)
#endif
}
rktio_ok_t rktio_copy_file_finish_permissions(rktio_t *rktio, rktio_file_copy_t *fc)
{
#ifdef RKTIO_SYSTEM_UNIX
int err;
do {
err = fchmod(rktio_fd_system_fd(rktio, fc->dest_fd), fc->mode);
} while ((err == -1) && (errno != EINTR));
if (err) {
get_posix_error();
return 0;
}
#endif
return 1;
}
void rktio_copy_file_stop(rktio_t *rktio, rktio_file_copy_t *fc)
{
#ifdef RKTIO_SYSTEM_UNIX