diff options
author | Jim Meyering <jim@meyering.net> | 2000-08-27 09:30:00 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2000-08-27 09:30:00 +0000 |
commit | 6bf3479c9f21791b1deecb82390c45a0afae8bc8 (patch) | |
tree | fe07777d41db42b6276e0243e8a05de3ebc03509 /src | |
parent | 2c8881fa4e5070105c6b19b28e6f9d12bae74fb6 (diff) | |
download | coreutils-6bf3479c9f21791b1deecb82390c45a0afae8bc8.tar.xz |
(copy_reg): New parameters: X and NEW_DST.
Remove the SPARSE_MODE parameter. Update caller.
Perform POSIX-mandated (for cp) open-with-O_WRONLY|O_TRUNC when
the regular destination file exists; upon failure, unlink
that existing file, then open again, but with O_WRONLY|O_CREAT.
(copy_internal): `force' in not related to interactive; remove
the conjunct.
Remove the entire `else if (x->force)' block; justifying
removal of the non-directory part is easy: POSIX requires we try
to open an existing regular file, so we can't unlink it beforehand.
The part that changes the mode on a directory to allow overwriting
isn't necessary.
Diffstat (limited to 'src')
-rw-r--r-- | src/copy.c | 73 |
1 files changed, 36 insertions, 37 deletions
diff --git a/src/copy.c b/src/copy.c index 0a62373ce..70054752d 100644 --- a/src/copy.c +++ b/src/copy.c @@ -167,12 +167,13 @@ copy_dir (const char *src_path_in, const char *dst_path_in, int new_dst, in the source file as holes in the destination file. (Holes are read as zeroes by the `read' system call.) Use DST_MODE as the 3rd argument in the call to open. + X provides many option settings. Return 0 if successful, -1 if an error occurred. - FIXME: describe sparse_mode. */ + *NEW_DST is as in copy_internal. */ static int copy_reg (const char *src_path, const char *dst_path, - enum Sparse_type sparse_mode, mode_t dst_mode) + const struct cp_options *x, mode_t dst_mode, int *new_dst) { char *buf; int buf_size; @@ -184,7 +185,7 @@ copy_reg (const char *src_path, const char *dst_path, int return_val = 0; off_t n_read_total = 0; int last_write_made_hole = 0; - int make_holes = (sparse_mode == SPARSE_ALWAYS); + int make_holes = (x->sparse_mode == SPARSE_ALWAYS); source_desc = open (src_path, O_RDONLY); if (source_desc < 0) @@ -202,7 +203,34 @@ copy_reg (const char *src_path, const char *dst_path, return -1; } - dest_desc = open (dst_path, O_WRONLY | O_CREAT | O_TRUNC, dst_mode); + /* These semantics are required for cp. + The if-block will be taken in move_mode. */ + if (*new_dst) + { + dest_desc = open (dst_path, O_WRONLY | O_CREAT, dst_mode); + } + else + { + dest_desc = open (dst_path, O_WRONLY | O_TRUNC, dst_mode); + + /* FIXME: Rename force to unlink_dest_upon_failed_open. */ + if (dest_desc < 0 && x->force) + { + if (unlink (dst_path)) + { + error (0, errno, _("cannot remove %s"), quote (dst_path)); + return_val = -1; + goto close_src_desc; + } + + /* Tell caller that the destination file was unlinked. */ + *new_dst = 1; + + /* Try the open again, but this time with different flags. */ + dest_desc = open (dst_path, O_WRONLY | O_CREAT, dst_mode); + } + } + if (dest_desc < 0) { error (0, errno, _("cannot create regular file %s"), quote (dst_path)); @@ -222,7 +250,7 @@ copy_reg (const char *src_path, const char *dst_path, buf_size = ST_BLKSIZE (sb); #if HAVE_STRUCT_STAT_ST_BLOCKS - if (sparse_mode == SPARSE_AUTO && S_ISREG (sb.st_mode)) + if (x->sparse_mode == SPARSE_AUTO && S_ISREG (sb.st_mode)) { /* Use a heuristic to determine whether SRC_PATH contains any sparse blocks. */ @@ -498,7 +526,7 @@ copy_internal (const char *src_path, const char *dst_path, if (!S_ISDIR (src_type) && x->interactive) { - if (euidaccess (dst_path, W_OK) != 0 && x->force) + if (euidaccess (dst_path, W_OK) != 0) { fprintf (stderr, _("%s: overwrite %s, overriding mode %04lo? "), @@ -579,35 +607,6 @@ copy_internal (const char *src_path, const char *dst_path, } new_dst = 1; } - else if (x->force) - { - if (S_ISDIR (dst_sb.st_mode)) - { - /* Temporarily change mode to allow overwriting. */ - if (euidaccess (dst_path, W_OK | X_OK) != 0 - && chmod (dst_path, S_IRWXU)) - { - error (0, errno, - _("cannot change permissions for %s"), - quote (dst_path)); - return 1; - } - } - else - { - if (unlink (dst_path) && errno != ENOENT) - { - error (0, errno, _("cannot remove old link to %s"), - quote (dst_path)); - if (x->failed_unlink_is_fatal) - return 1; - } - else - { - new_dst = 1; - } - } - } } } @@ -827,8 +826,8 @@ copy_internal (const char *src_path, const char *dst_path, /* POSIX says the permission bits of the source file must be used as the 3rd argument in the open call, but that's not consistent with historical practice. */ - if (copy_reg (src_path, dst_path, x->sparse_mode, - get_dest_mode (x, src_mode))) + if (copy_reg (src_path, dst_path, x, + get_dest_mode (x, src_mode), &new_dst)) goto un_backup; } else |