225 lines
6.6 KiB
Diff
225 lines
6.6 KiB
Diff
|
Index: sed-4.1.5/sed/sed.c
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/sed/sed.c
|
|||
|
+++ sed-4.1.5/sed/sed.c
|
|||
|
@@ -70,6 +70,11 @@ bool no_default_output = false;
|
|||
|
/* If set, reset line counts on every new file. */
|
|||
|
bool separate_files = false;
|
|||
|
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+/* If set, follow symlinks when processing in place */
|
|||
|
+bool follow_symlinks = false;
|
|||
|
+#endif
|
|||
|
+
|
|||
|
/* How do we edit files in-place? (we don't if NULL) */
|
|||
|
char *in_place_extension = NULL;
|
|||
|
|
|||
|
@@ -105,6 +110,10 @@ Usage: %s [OPTION]... {script-only-if-no
|
|||
|
add the script to the commands to be executed\n"));
|
|||
|
fprintf(out, _(" -f script-file, --file=script-file\n\
|
|||
|
add the contents of script-file to the commands to be executed\n"));
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+ fprintf(out, _(" --follow-symlinks\n\
|
|||
|
+ follow symlinks when processing in place\n"));
|
|||
|
+#endif
|
|||
|
fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\
|
|||
|
edit files in place (makes backup if extension supplied)\n"));
|
|||
|
fprintf(out, _(" -l N, --line-length=N\n\
|
|||
|
@@ -163,6 +172,9 @@ main(argc, argv)
|
|||
|
{"unbuffered", 0, NULL, 'u'},
|
|||
|
{"version", 0, NULL, 'v'},
|
|||
|
{"help", 0, NULL, 'h'},
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+ {"follow-symlinks", 0, NULL, 'F'},
|
|||
|
+#endif
|
|||
|
{NULL, 0, NULL, 0}
|
|||
|
};
|
|||
|
|
|||
|
@@ -215,6 +227,12 @@ main(argc, argv)
|
|||
|
the_program = compile_file(the_program, optarg);
|
|||
|
break;
|
|||
|
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+ case 'F':
|
|||
|
+ follow_symlinks = true;
|
|||
|
+ break;
|
|||
|
+#endif
|
|||
|
+
|
|||
|
case 'i':
|
|||
|
separate_files = true;
|
|||
|
if (optarg == NULL)
|
|||
|
Index: sed-4.1.5/lib/utils.c
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/lib/utils.c
|
|||
|
+++ sed-4.1.5/lib/utils.c
|
|||
|
@@ -35,6 +35,13 @@
|
|||
|
# include <stdlib.h>
|
|||
|
#endif /* HAVE_STDLIB_H */
|
|||
|
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+# include <sys/types.h>
|
|||
|
+# include <sys/stat.h>
|
|||
|
+# include <unistd.h>
|
|||
|
+# include <libgen.h>
|
|||
|
+#endif /* ENABLE_FOLLOW_SYMLINKS */
|
|||
|
+
|
|||
|
#include "utils.h"
|
|||
|
|
|||
|
const char *myname;
|
|||
|
@@ -315,6 +322,65 @@ do_ck_fclose(fp)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+static char buf[2048], buf2[2048];
|
|||
|
+static size_t bufsize = sizeof (buf);
|
|||
|
+
|
|||
|
+/* Follow symlink and panic if something fails. Returned value is
|
|||
|
+ ultimate symlink target, stored in temporary buffer. You need to
|
|||
|
+ strdup the return value, if you intend to use it later.*/
|
|||
|
+const char *
|
|||
|
+ck_follow_symlink(const char * fname)
|
|||
|
+{
|
|||
|
+ static struct stat statbuf;
|
|||
|
+ int err;
|
|||
|
+ char * dir;
|
|||
|
+
|
|||
|
+ if (strlen (fname) >= bufsize)
|
|||
|
+ panic("ck_follow_symlink: file name too long");
|
|||
|
+ strcpy (buf, fname);
|
|||
|
+
|
|||
|
+ while (1)
|
|||
|
+ {
|
|||
|
+ err = lstat (buf, &statbuf);
|
|||
|
+
|
|||
|
+ if (err != 0)
|
|||
|
+ panic("ck_follow_symlink: couldn't lstat %s: %s", buf, 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 */
|
|||
|
+ if (buf2[0] != '/')
|
|||
|
+ {
|
|||
|
+ dir = dirname (buf); // dir part of orig path
|
|||
|
+ int len = strlen (dir); // orig path len
|
|||
|
+ 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;
|
|||
|
+}
|
|||
|
+#endif /* ENABLE_FOLLOW_SYMLINKS */
|
|||
|
+
|
|||
|
/* Panic on failing rename */
|
|||
|
void
|
|||
|
ck_rename (from, to, unlink_if_fail)
|
|||
|
Index: sed-4.1.5/lib/utils.h
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/lib/utils.h
|
|||
|
+++ sed-4.1.5/lib/utils.h
|
|||
|
@@ -27,6 +27,9 @@ void ck_fwrite P_((const VOID *ptr, size
|
|||
|
size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
|
|||
|
void ck_fflush P_((FILE *stream));
|
|||
|
void ck_fclose P_((FILE *stream));
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+const char *ck_follow_symlink P_((const char *path));
|
|||
|
+#endif
|
|||
|
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));
|
|||
|
Index: sed-4.1.5/sed/execute.c
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/sed/execute.c
|
|||
|
+++ sed-4.1.5/sed/execute.c
|
|||
|
@@ -711,16 +711,34 @@ closedown(input)
|
|||
|
|
|||
|
if (in_place_extension && output_file.fp != NULL)
|
|||
|
{
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+ char *target_name;
|
|||
|
+
|
|||
|
+ if (follow_symlinks)
|
|||
|
+ target_name = ck_strdup(ck_follow_symlink(input->in_file_name));
|
|||
|
+ else
|
|||
|
+ target_name = ck_strdup(input->in_file_name);
|
|||
|
+#else
|
|||
|
+ const char *target_name;
|
|||
|
+
|
|||
|
+ target_name = input->in_file_name;
|
|||
|
+#endif
|
|||
|
+
|
|||
|
ck_fclose (output_file.fp);
|
|||
|
if (strcmp(in_place_extension, "*") != 0)
|
|||
|
{
|
|||
|
- 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);
|
|||
|
+ char *backup_file_name = get_backup_file_name(target_name);
|
|||
|
+ ck_rename (target_name, backup_file_name, input->out_file_name);
|
|||
|
+
|
|||
|
free (backup_file_name);
|
|||
|
}
|
|||
|
|
|||
|
- ck_rename (input->out_file_name, input->in_file_name, input->out_file_name);
|
|||
|
+ ck_rename (input->out_file_name, target_name, input->out_file_name);
|
|||
|
+
|
|||
|
free (input->out_file_name);
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+ free (target_name);
|
|||
|
+#endif
|
|||
|
}
|
|||
|
|
|||
|
input->fp = NULL;
|
|||
|
Index: sed-4.1.5/sed/sed.h
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/sed/sed.h
|
|||
|
+++ sed-4.1.5/sed/sed.h
|
|||
|
@@ -219,6 +219,11 @@ extern bool no_default_output;
|
|||
|
/* If set, reset line counts on every new file. */
|
|||
|
extern bool separate_files;
|
|||
|
|
|||
|
+#ifdef ENABLE_FOLLOW_SYMLINKS
|
|||
|
+/* If set, follow symlinks when invoked with -i option */
|
|||
|
+extern bool follow_symlinks;
|
|||
|
+#endif
|
|||
|
+
|
|||
|
/* Do we need to be pedantically POSIX compliant? */
|
|||
|
extern enum posixicity_types posixicity;
|
|||
|
|
|||
|
Index: sed-4.1.5/configure.ac
|
|||
|
===================================================================
|
|||
|
--- sed-4.1.5.orig/configure.ac
|
|||
|
+++ sed-4.1.5/configure.ac
|
|||
|
@@ -117,6 +117,13 @@ enable_html=no)
|
|||
|
|
|||
|
AM_CONDITIONAL(BUILD_HTML, test "x$enable_html" != xno)
|
|||
|
|
|||
|
+# follow symlinks
|
|||
|
+AC_CHECK_FUNC(lstat, have_lstat=yes)
|
|||
|
+AC_CHECK_FUNC(readlink, have_readlink=yes)
|
|||
|
+if test "x$have_lstat" = xyes -a "x$have_readlink" = xyes; then
|
|||
|
+ AC_DEFINE(ENABLE_FOLLOW_SYMLINKS, ,[Follow symlinks when processing in place])
|
|||
|
+fi
|
|||
|
+
|
|||
|
: ${TEXI2HTML=texi2html -monolithic}
|
|||
|
AC_SUBST(TEXI2HTML)
|
|||
|
|