sed/sed-4.1.5-follow.patch

168 lines
4.7 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 -Burp sed-4.1.5-orig/lib/utils.c sed-4.1.5-follow/lib/utils.c
--- sed-4.1.5-orig/lib/utils.c 2005-06-21 16:09:40.000000000 +0200
+++ sed-4.1.5-follow/lib/utils.c 2006-12-07 19:08:02.000000000 +0100
@@ -35,6 +35,12 @@
# include <stdlib.h>
#endif /* HAVE_STDLIB_H */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/sendfile.h>
+#include <fcntl.h>
+
#include "utils.h"
const char *myname;
@@ -315,32 +321,99 @@ do_ck_fclose(fp)
}
-/* Panic on failing rename */
-void
-ck_rename (from, to, unlink_if_fail)
- const char *from, *to;
- const char *unlink_if_fail;
+#include <libgen.h>
+
+/* Follow symlink and panic if something fails. Returned value is
+ ultimate symlink target, stored in malloc'd buffer.*/
+const char*
+ck_follow_symlink(const char * fname)
{
- int rd = rename (from, to);
- if (rd != -1)
- return;
+ static struct stat statbuf;
+ int err;
+ char * dir;
+
+ static size_t bufsize = 1024;
+ char * buf = malloc (bufsize);
+ char * buf2 = alloca (bufsize);
+
+ if (strlen (fname) >= bufsize)
+ panic("ck_follow_symlink: file name too long");
+ strcpy (buf, fname);
- if (unlink_if_fail)
+ while (1)
{
- int save_errno = errno;
- errno = 0;
- unlink (unlink_if_fail);
+ err = lstat (buf, &statbuf);
+
+ if (err != 0)
+ panic("ck_follow_symlink: couldn't lstat %s: %s", buf, strerror(errno));
- /* 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));
+ if ((statbuf.st_mode & S_IFLNK) == S_IFLNK)
+ {
+ err = readlink (buf, buf2, bufsize);
+
+ if (err < 0)
+ panic("ck_follow_symlink: readlink failed on %s: %s", buf, strerror(errno));
+ else if (err == bufsize)
+ panic("ck_follow_symlink: pointee name too long");
+ else
+ buf2 [err] = '\0';
+
+ /* need to handle relative paths with care */
+ dir = dirname (buf); // dir part of orig path
+ int len = strlen (dir); // orig path len
+ if (buf2[0] != '/' && len != 1 && dir[0] != '.')
+ {
+ buf[len] = '/';
+ strncpy (buf+len+1, buf2, bufsize - len - 1);
+ if (buf[bufsize-1] != 0)
+ panic("ck_follow_symlink: pointee name too long");
+ }
+ else
+ {
+ strcpy (buf, buf2);
+ }
+ }
+ else
+ break;
+ }
+
+ return buf;
+}
+/* Panic on failing unlink */
+void
+ck_unlink (name)
+ const char *name;
+{
+ if (unlink (name) == -1)
+ panic (_("cannot remove %s: %s"), name, strerror (errno));
+}
+
+/* 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;
}
- panic (_("cannot rename %s: %s"), from, strerror (errno));
+ return rd != -1;
}
+/* 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));
+}
diff -Burp sed-4.1.5-orig/lib/utils.h sed-4.1.5-follow/lib/utils.h
--- sed-4.1.5-orig/lib/utils.h 2005-06-21 16:09:40.000000000 +0200
+++ sed-4.1.5-follow/lib/utils.h 2006-12-07 19:00:11.000000000 +0100
@@ -29,6 +29,7 @@ void ck_fflush P_((FILE *stream));
void ck_fclose P_((FILE *stream));
size_t ck_getline P_((char **text, size_t *buflen, FILE *stream));
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_malloc P_((size_t size));
--- sed-4.1.5-orig/sed/execute.c 2006-12-08 16:33:20.000000000 +0100
+++ sed-4.1.5-follow/sed/execute.c 2006-12-07 18:53:11.000000000 +0100
@@ -712,16 +712,18 @@
if (in_place_extension && output_file.fp != NULL)
{
+ char * target_name = ck_strdup (ck_follow_symlink (input->in_file_name));
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(input->in_file_name);
- ck_rename (input->in_file_name, backup_file_name, input->out_file_name);
free (backup_file_name);
}
+ ck_rename (input->out_file_name, target_name, input->out_file_name);
- ck_rename (input->out_file_name, input->in_file_name, input->out_file_name);
free (input->out_file_name);
+ free (target_name);
}
input->fp = NULL;