| 1 |
diff -Burp sed-4.1.5-orig/lib/utils.c sed-4.1.5-follow/lib/utils.c
|
| 2 |
--- sed-4.1.5-orig/lib/utils.c 2005-06-21 16:09:40.000000000 +0200
|
| 3 |
+++ sed-4.1.5-follow/lib/utils.c 2006-12-07 19:08:02.000000000 +0100
|
| 4 |
@@ -35,6 +35,12 @@
|
| 5 |
# include <stdlib.h>
|
| 6 |
#endif /* HAVE_STDLIB_H */
|
| 7 |
|
| 8 |
+#include <sys/types.h>
|
| 9 |
+#include <sys/stat.h>
|
| 10 |
+#include <unistd.h>
|
| 11 |
+#include <sys/sendfile.h>
|
| 12 |
+#include <fcntl.h>
|
| 13 |
+
|
| 14 |
#include "utils.h"
|
| 15 |
|
| 16 |
const char *myname;
|
| 17 |
@@ -315,32 +321,99 @@ do_ck_fclose(fp)
|
| 18 |
}
|
| 19 |
|
| 20 |
|
| 21 |
-/* Panic on failing rename */
|
| 22 |
-void
|
| 23 |
-ck_rename (from, to, unlink_if_fail)
|
| 24 |
- const char *from, *to;
|
| 25 |
- const char *unlink_if_fail;
|
| 26 |
+#include <libgen.h>
|
| 27 |
+
|
| 28 |
+/* Follow symlink and panic if something fails. Returned value is
|
| 29 |
+ ultimate symlink target, stored in malloc'd buffer.*/
|
| 30 |
+const char*
|
| 31 |
+ck_follow_symlink(const char * fname)
|
| 32 |
{
|
| 33 |
- int rd = rename (from, to);
|
| 34 |
- if (rd != -1)
|
| 35 |
- return;
|
| 36 |
+ static struct stat statbuf;
|
| 37 |
+ int err;
|
| 38 |
+ char * dir;
|
| 39 |
+
|
| 40 |
+ static size_t bufsize = 1024;
|
| 41 |
+ char * buf = malloc (bufsize);
|
| 42 |
+ char * buf2 = alloca (bufsize);
|
| 43 |
+
|
| 44 |
+ if (strlen (fname) >= bufsize)
|
| 45 |
+ panic("ck_follow_symlink: file name too long");
|
| 46 |
+ strcpy (buf, fname);
|
| 47 |
|
| 48 |
- if (unlink_if_fail)
|
| 49 |
+ while (1)
|
| 50 |
{
|
| 51 |
- int save_errno = errno;
|
| 52 |
- errno = 0;
|
| 53 |
- unlink (unlink_if_fail);
|
| 54 |
+ err = lstat (buf, &statbuf);
|
| 55 |
+
|
| 56 |
+ if (err != 0)
|
| 57 |
+ panic("ck_follow_symlink: couldn't lstat %s: %s", buf, strerror(errno));
|
| 58 |
|
| 59 |
- /* Failure to remove the temporary file is more severe, so trigger it first. */
|
| 60 |
- if (errno != 0)
|
| 61 |
- panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
|
| 62 |
+ if ((statbuf.st_mode & S_IFLNK) == S_IFLNK)
|
| 63 |
+ {
|
| 64 |
+ err = readlink (buf, buf2, bufsize);
|
| 65 |
+
|
| 66 |
+ if (err < 0)
|
| 67 |
+ panic("ck_follow_symlink: readlink failed on %s: %s", buf, strerror(errno));
|
| 68 |
+ else if (err == bufsize)
|
| 69 |
+ panic("ck_follow_symlink: pointee name too long");
|
| 70 |
+ else
|
| 71 |
+ buf2 [err] = '\0';
|
| 72 |
+
|
| 73 |
+ /* need to handle relative paths with care */
|
| 74 |
+ dir = dirname (buf); // dir part of orig path
|
| 75 |
+ int len = strlen (dir); // orig path len
|
| 76 |
+ if (buf2[0] != '/' && len != 1 && dir[0] != '.')
|
| 77 |
+ {
|
| 78 |
+ buf[len] = '/';
|
| 79 |
+ strncpy (buf+len+1, buf2, bufsize - len - 1);
|
| 80 |
+ if (buf[bufsize-1] != 0)
|
| 81 |
+ panic("ck_follow_symlink: pointee name too long");
|
| 82 |
+ }
|
| 83 |
+ else
|
| 84 |
+ {
|
| 85 |
+ strcpy (buf, buf2);
|
| 86 |
+ }
|
| 87 |
+ }
|
| 88 |
+ else
|
| 89 |
+ break;
|
| 90 |
+ }
|
| 91 |
+
|
| 92 |
+ return buf;
|
| 93 |
+}
|
| 94 |
|
| 95 |
+/* Panic on failing unlink */
|
| 96 |
+void
|
| 97 |
+ck_unlink (name)
|
| 98 |
+ const char *name;
|
| 99 |
+{
|
| 100 |
+ if (unlink (name) == -1)
|
| 101 |
+ panic (_("cannot remove %s: %s"), name, strerror (errno));
|
| 102 |
+}
|
| 103 |
+
|
| 104 |
+/* Attempt to unlink denoted file if operation rd failed. */
|
| 105 |
+static int
|
| 106 |
+_unlink_if_fail (rd, unlink_if_fail)
|
| 107 |
+ int rd;
|
| 108 |
+ const char *unlink_if_fail;
|
| 109 |
+{
|
| 110 |
+ if (rd == -1 && unlink_if_fail)
|
| 111 |
+ {
|
| 112 |
+ int save_errno = errno;
|
| 113 |
+ ck_unlink (unlink_if_fail);
|
| 114 |
errno = save_errno;
|
| 115 |
}
|
| 116 |
|
| 117 |
- panic (_("cannot rename %s: %s"), from, strerror (errno));
|
| 118 |
+ return rd != -1;
|
| 119 |
}
|
| 120 |
|
| 121 |
+/* Panic on failing rename */
|
| 122 |
+void
|
| 123 |
+ck_rename (from, to, unlink_if_fail)
|
| 124 |
+ const char *from, *to;
|
| 125 |
+ const char *unlink_if_fail;
|
| 126 |
+{
|
| 127 |
+ if (!_unlink_if_fail (rename (from, to), unlink_if_fail))
|
| 128 |
+ panic (_("cannot rename %s: %s"), from, strerror (errno));
|
| 129 |
+}
|
| 130 |
|
| 131 |
|
| 132 |
|
| 133 |
diff -Burp sed-4.1.5-orig/lib/utils.h sed-4.1.5-follow/lib/utils.h
|
| 134 |
--- sed-4.1.5-orig/lib/utils.h 2005-06-21 16:09:40.000000000 +0200
|
| 135 |
+++ sed-4.1.5-follow/lib/utils.h 2006-12-07 19:00:11.000000000 +0100
|
| 136 |
@@ -29,6 +29,7 @@ void ck_fflush P_((FILE *stream));
|
| 137 |
void ck_fclose P_((FILE *stream));
|
| 138 |
size_t ck_getline P_((char **text, size_t *buflen, FILE *stream));
|
| 139 |
FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base));
|
| 140 |
+const char* ck_follow_symlink P_((const char * fname));
|
| 141 |
void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail));
|
| 142 |
|
| 143 |
VOID *ck_malloc P_((size_t size));
|
| 144 |
--- sed-4.1.5-orig/sed/execute.c 2006-12-08 16:33:20.000000000 +0100
|
| 145 |
+++ sed-4.1.5-follow/sed/execute.c 2006-12-07 18:53:11.000000000 +0100
|
| 146 |
@@ -712,16 +712,18 @@
|
| 147 |
|
| 148 |
if (in_place_extension && output_file.fp != NULL)
|
| 149 |
{
|
| 150 |
+ char * target_name = ck_strdup (ck_follow_symlink (input->in_file_name));
|
| 151 |
ck_fclose (output_file.fp);
|
| 152 |
if (strcmp(in_place_extension, "*") != 0)
|
| 153 |
{
|
| 154 |
+ char *backup_file_name = get_backup_file_name(target_name);
|
| 155 |
+ ck_rename (target_name, backup_file_name, input->out_file_name);
|
| 156 |
- char *backup_file_name = get_backup_file_name(input->in_file_name);
|
| 157 |
- ck_rename (input->in_file_name, backup_file_name, input->out_file_name);
|
| 158 |
free (backup_file_name);
|
| 159 |
}
|
| 160 |
|
| 161 |
+ ck_rename (input->out_file_name, target_name, input->out_file_name);
|
| 162 |
- ck_rename (input->out_file_name, input->in_file_name, input->out_file_name);
|
| 163 |
free (input->out_file_name);
|
| 164 |
+ free (target_name);
|
| 165 |
}
|
| 166 |
|
| 167 |
input->fp = NULL;
|