diff -Burp sed-4.1.5/doc/sed.1 sed-4.1.5-f+c/doc/sed.1 --- sed-4.1.5/doc/sed.1 2006-02-03 10:27:35.000000000 +0100 +++ sed-4.1.5-f+c/doc/sed.1 2006-12-08 16:42:59.000000000 +0100 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.28. -.TH SED "1" "February 2006" "sed version 4.1.4" "User Commands" +.TH SED "1" "June 2006" "sed version 4.1.5" "User Commands" .SH NAME sed \- stream editor for filtering and transforming text .SH SYNOPSIS @@ -36,6 +36,11 @@ add the contents of script-file to the c .IP edit files in place (makes backup if extension supplied) .HP +\fB\-c\fR, \fB\-\-copy\fR +.IP +use copy instead of rename when shuffling files in \fB\-i\fR mode +(avoids change of input file ownership) +.HP \fB\-l\fR N, \fB\-\-line\-length\fR=\fIN\fR .IP specify the desired line-wrap length for the `l' command diff -Burp sed-4.1.5/lib/utils.c sed-4.1.5-f+c/lib/utils.c --- sed-4.1.5/lib/utils.c 2006-12-08 16:41:41.000000000 +0100 +++ sed-4.1.5-f+c/lib/utils.c 2006-12-08 16:42:59.000000000 +0100 @@ -405,6 +406,55 @@ _unlink_if_fail (rd, unlink_if_fail) return rd != -1; } +/* Copy contents between files. */ +static int +_copy (from, to) + const char *from, *to; +{ + static size_t bufsize = 1024; + FILE *infile, *outfile; + int retval = 0; + char * buf; + + errno = 0; + + infile = fopen (from, "r"); + if (infile == NULL) + return -1; + + outfile = fopen (to, "w"); + if (outfile == NULL) + { + fclose (infile); + return -1; + } + + buf = alloca (bufsize); + while (1) + { + size_t bytes_in = fread (buf, 1, bufsize, infile); + size_t bytes_out; + if (bytes_in == 0) + { + if (ferror (infile)) + retval = -1; + break; + } + + bytes_out = fwrite (buf, 1, bytes_in, outfile); + if (bytes_out != bytes_in) + { + retval = -1; + break; + } + } + + fclose (outfile); + fclose (infile); + + return retval; +} + /* Panic on failing rename */ void ck_rename (from, to, unlink_if_fail) @@ -415,6 +465,26 @@ ck_rename (from, to, unlink_if_fail) panic (_("cannot rename %s: %s"), from, strerror (errno)); } +/* Attempt to copy file contents between the files. */ +void +ck_fcmove (from, to, unlink_if_fail) + const char *from, *to; + const char *unlink_if_fail; +{ + if (!_unlink_if_fail (_copy (from, to), unlink_if_fail)) + panic (_("cannot copy %s to %s: %s"), from, to, strerror (errno)); +} + +/* Copy contents between files, and then unlink the source. */ +void +ck_fcopy (from, to, unlink_if_fail) + const char *from, *to; + const char *unlink_if_fail; +{ + ck_fcmove (from, to, unlink_if_fail); + ck_unlink (from); +} + /* Panic on failing malloc */ diff -Burp sed-4.1.5/lib/utils.h sed-4.1.5-f+c/lib/utils.h --- sed-4.1.5/lib/utils.h 2006-12-08 16:41:41.000000000 +0100 +++ sed-4.1.5-f+c/lib/utils.h 2006-12-08 16:42:59.000000000 +0100 @@ -31,6 +31,8 @@ size_t ck_getline P_((char **text, size_ FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base)); const char* ck_follow_symlink P_((const char * fname)); void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail)); +void ck_fcopy P_((const char *from, const char *to, const char *unlink_if_fail)); +void ck_fcmove P_((const char *from, const char *to, const char *unlink_if_fail)); VOID *ck_malloc P_((size_t size)); VOID *xmalloc P_((size_t size)); diff -Burp sed-4.1.5/sed/execute.c sed-4.1.5-f+c/sed/execute.c --- sed-4.1.5/sed/execute.c 2006-12-08 16:41:41.000000000 +0100 +++ sed-4.1.5-f+c/sed/execute.c 2006-12-08 16:42:59.000000000 +0100 @@ -716,12 +716,14 @@ closedown(input) ck_fclose (output_file.fp); if (strcmp(in_place_extension, "*") != 0) { - char *backup_file_name = get_backup_file_name(target_name); - ck_rename (target_name, backup_file_name, input->out_file_name); + char *backup_file_name = get_backup_file_name(target_name); + (copy_instead_of_rename?ck_fcmove:ck_rename) + (target_name, backup_file_name, input->out_file_name); free (backup_file_name); } - ck_rename (input->out_file_name, target_name, input->out_file_name); + (copy_instead_of_rename?ck_fcopy:ck_rename) + (input->out_file_name, target_name, input->out_file_name); free (input->out_file_name); free (target_name); } diff -Burp sed-4.1.5/sed/sed.c sed-4.1.5-f+c/sed/sed.c --- sed-4.1.5/sed/sed.c 2005-06-21 16:09:47.000000000 +0200 +++ sed-4.1.5-f+c/sed/sed.c 2006-12-08 16:42:59.000000000 +0100 @@ -73,6 +73,10 @@ bool separate_files = false; /* How do we edit files in-place? (we don't if NULL) */ char *in_place_extension = NULL; +/* Do we use copy or rename when in in-place edit mode? (boolean + value, non-zero for copy, zero for rename).*/ +int copy_instead_of_rename = 0; + /* Do we need to be pedantically POSIX compliant? */ enum posixicity_types posixicity; @@ -107,6 +111,9 @@ Usage: %s [OPTION]... {script-only-if-no add the contents of script-file to the commands to be executed\n")); fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\ edit files in place (makes backup if extension supplied)\n")); + fprintf(out, _(" -c, --copy\n\ + use copy instead of rename when shuffling files in -i mode\n\ + (avoids change of input file ownership)\n")); fprintf(out, _(" -l N, --line-length=N\n\ specify the desired line-wrap length for the `l' command\n")); fprintf(out, _(" --posix\n\ @@ -142,9 +149,9 @@ main(argc, argv) char **argv; { #ifdef REG_PERL -#define SHORTOPTS "snrRue:f:l:i::V:" +#define SHORTOPTS "csnrRue:f:l:i::V:" #else -#define SHORTOPTS "snrue:f:l:i::V:" +#define SHORTOPTS "csnrue:f:l:i::V:" #endif static struct option longopts[] = { @@ -155,6 +162,7 @@ main(argc, argv) {"expression", 1, NULL, 'e'}, {"file", 1, NULL, 'f'}, {"in-place", 2, NULL, 'i'}, + {"copy", 0, NULL, 'c'}, {"line-length", 1, NULL, 'l'}, {"quiet", 0, NULL, 'n'}, {"posix", 0, NULL, 'p'}, @@ -215,6 +223,10 @@ main(argc, argv) the_program = compile_file(the_program, optarg); break; + case 'c': + copy_instead_of_rename = true; + break; + case 'i': separate_files = true; if (optarg == NULL) @@ -284,6 +296,12 @@ to the extent permitted by law.\n\ } } + if (copy_instead_of_rename && in_place_extension == NULL) + { + fprintf (stderr, _("Error: -c used without -i.\n")); + usage(4); + } + if (!the_program) { if (optind < argc) diff -Burp sed-4.1.5/sed/sed.h sed-4.1.5-f+c/sed/sed.h --- sed-4.1.5/sed/sed.h 2006-12-08 16:41:41.000000000 +0100 +++ sed-4.1.5-f+c/sed/sed.h 2006-12-08 16:42:59.000000000 +0100 @@ -228,6 +228,10 @@ extern countT lcmd_out_line_len; /* How do we edit files in-place? (we don't if NULL) */ extern char *in_place_extension; +/* Do we use copy or rename when in in-place edit mode? (boolean + value, non-zero for copy, zero for rename).*/ +extern int copy_instead_of_rename; + /* Should we use EREs? */ extern bool use_extended_syntax_p;