File sed-follow_symlinks.patch of Package sed

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)
 
openSUSE Build Service is sponsored by