sed/sed-4.2.1-copy.patch

274 lines
7.4 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/doc/sed.1 b/doc/sed.1
index 42a0a28..bb235c8 100644
--- a/doc/sed.1
+++ b/doc/sed.1
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.28.
-.TH SED "1" "June 2009" "sed version 4.2.1" "User Commands"
+.TH SED "1" "February 2010" "sed version 4.2.1" "User Commands"
.SH NAME
sed \- stream editor for filtering and transforming text
.SH SYNOPSIS
@@ -40,6 +40,10 @@ follow symlinks when processing in place
.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
+.HP
\fB\-l\fR N, \fB\-\-line\-length\fR=\fIN\fR
.IP
specify the desired line-wrap length for the `l' command
diff --git a/sed/execute.c b/sed/execute.c
index af8c4d2..c05b418 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -822,11 +822,13 @@ closedown(input)
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);
+ (copy_instead_of_rename?ck_fccopy: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_fcmove:ck_rename)
+ (input->out_file_name, target_name, input->out_file_name);
free (input->out_file_name);
}
else
diff --git a/sed/sed.c b/sed/sed.c
index 723958d..1fbb279 100644
--- a/sed/sed.c
+++ b/sed/sed.c
@@ -75,6 +75,10 @@ bool follow_symlinks = 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;
+
/* The mode to use to read files, either "rt" or "rb". */
char *read_mode = "rt";
@@ -135,6 +139,8 @@ Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\
#endif
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"));
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__)
fprintf(out, _(" -b, --binary\n\
open files in binary mode (CR+LFs are not processed specially)\n"));
@@ -174,9 +180,9 @@ main(argc, argv)
char **argv;
{
#ifdef REG_PERL
-#define SHORTOPTS "bsnrRuEe:f:l:i::V:"
+#define SHORTOPTS "bcsnrRuEe:f:l:i::V:"
#else
-#define SHORTOPTS "bsnruEe:f:l:i::V:"
+#define SHORTOPTS "bcsnruEe:f:l:i::V:"
#endif
static struct option longopts[] = {
@@ -188,6 +194,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'},
@@ -254,6 +261,10 @@ main(argc, argv)
case 'F':
follow_symlinks = true;
+ break;
+
+ case 'c':
+ copy_instead_of_rename = true;
break;
case 'i':
@@ -334,6 +345,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 --git a/sed/sed.h b/sed/sed.h
index 6b4101d..d4d9aa9 100644
--- a/sed/sed.h
+++ b/sed/sed.h
@@ -233,6 +233,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;
+
/* The mode to use to read files, either "rt" or "rb". */
extern char *read_mode;
diff --git a/sed/utils.c b/sed/utils.c
index 241ef1d..ebe6030 100644
--- a/sed/utils.c
+++ b/sed/utils.c
@@ -39,6 +39,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
+#include <fcntl.h>
#include "utils.h"
#include "pathmax.h"
@@ -408,33 +409,109 @@ follow_symlink(const char *fname)
return fname;
#endif /* ENABLE_FOLLOW_SYMLINKS */
}
+
-/* Panic on failing rename */
+/* Panic on failing unlink */
void
-ck_rename (from, to, unlink_if_fail)
- const char *from, *to;
- const char *unlink_if_fail;
+ck_unlink (name)
+ const char *name;
{
- int rd = rename (from, to);
- if (rd != -1)
- return;
+ if (unlink (name) == -1)
+ panic (_("cannot remove %s: %s"), name, strerror (errno));
+}
- if (unlink_if_fail)
+/* Attempt to unlink denoted file if operation rd failed. */
+static int
+_unlink_if_fail (rd, unlink_if_fail)
+ int rd;
+ const char *unlink_if_fail;
+{
+ if (rd == -1 && unlink_if_fail)
{
int save_errno = errno;
+ ck_unlink (unlink_if_fail);
+ errno = save_errno;
+ }
+
+ return rd != -1;
+}
+
+/* Copy contents between files. */
+static int
+_copy (from, to)
+ const char *from, *to;
+{
+ static char buf[4096];
+
+ FILE *infile, *outfile;
+ int c, retval = 0;
errno = 0;
- unlink (unlink_if_fail);
- /* Failure to remove the temporary file is more severe, so trigger it first. */
- if (errno != 0)
- panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
+ infile = fopen (from, "r");
+ if (infile == NULL)
+ return -1;
- errno = save_errno;
+ outfile = fopen (to, "w");
+ if (outfile == NULL)
+ {
+ fclose (infile);
+ return -1;
+ }
+
+ while (1)
+ {
+ size_t bytes_in = fread (buf, 1, sizeof (buf), 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)
+ const char *from, *to;
+ const char *unlink_if_fail;
+{
+ if (!_unlink_if_fail (rename (from, to), unlink_if_fail))
panic (_("cannot rename %s: %s"), from, strerror (errno));
}
+/* Attempt to copy file contents between the files. */
+void
+ck_fccopy (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_fcmove (from, to, unlink_if_fail)
+ const char *from, *to;
+ const char *unlink_if_fail;
+{
+ ck_fccopy (from, to, unlink_if_fail);
+ ck_unlink (from);
+}
diff --git a/sed/utils.h b/sed/utils.h
index d3f431d..b915596 100644
--- a/sed/utils.h
+++ b/sed/utils.h
@@ -32,6 +32,8 @@ const char *follow_symlink P_((const char *path));
size_t ck_getline P_((char **text, size_t *buflen, FILE *stream));
FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base));
void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail));
+void ck_fccopy 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));