Hello,

By modifying install to support DESTDIR I was able to effortlessly
create packages for many source distributions that do not support
DESTDIR but use install.

This patch adds the -P and --destdir options, which, if present,
prefix their argument or the value of $DESTDIR to the destination.

Please consider adding this functionality to install.

Thank you,

Etienne Laurin
--- delme/coreutils-7.4/src/install.c	2009-04-24 08:59:06.000000000 -0400
+++ src/install.c	2009-07-01 15:58:33.000000000 -0400
@@ -126,6 +126,9 @@
 /* If true, install a directory instead of a regular file. */
 static bool dir_arg;
 
+/* If true, prefix destination directory with value of DESTDIR */
+static char *destdir;
+
 /* Program used to strip binaries, "strip" is default */
 static char const *strip_program = "strip";
 
@@ -158,6 +161,7 @@
   {"suffix", required_argument, NULL, 'S'},
   {"target-directory", required_argument, NULL, 't'},
   {"verbose", no_argument, NULL, 'v'},
+  {"destdir", optional_argument, NULL, 'P'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -420,6 +424,24 @@
 	  : EXIT_FAILURE);
 }
 
+/* point dst new a new filename prefixed with pre */
+void
+add_prefix(char *pre, char **dst){
+  char new[PATH_MAX];
+  if(!pre)
+    return;
+  size_t len = strlen(pre);
+  strncpy(new, pre, PATH_MAX - 1);
+  if(**dst != '/'){
+    getcwd(new + len, PATH_MAX - len);
+    len = strlen(new);
+    new[len] = '/';
+    len++;
+  }
+  strncpy(new + len, *dst, PATH_MAX - len - 1);
+  *dst = new;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -460,7 +482,7 @@
      we'll actually use backup_suffix_string.  */
   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
 
-  while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z:", long_options,
+  while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pP::t:TvS:Z:", long_options,
 			      NULL)) != -1)
     {
       switch (optc)
@@ -507,6 +529,18 @@
 	case 'p':
 	  x.preserve_timestamps = true;
 	  break;
+        case 'P':
+          if(destdir){
+	    error (EXIT_FAILURE, 0,
+		   _("multiple destdir options specified"));
+          }else if(optarg){
+            destdir = optarg;
+          }else{
+            char *env_destdir = getenv("DESTDIR");
+            if(env_destdir)
+              destdir = xstrdup(env_destdir);
+          }
+          break;
 	case 'S':
 	  make_backups = true;
 	  backup_suffix_string = optarg;
@@ -516,15 +550,7 @@
 	    error (EXIT_FAILURE, 0,
 		   _("multiple target directories specified"));
 	  else
-	    {
-	      struct stat st;
-	      if (stat (optarg, &st) != 0)
-		error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
-	      if (! S_ISDIR (st.st_mode))
-		error (EXIT_FAILURE, 0, _("target %s is not a directory"),
-		       quote (optarg));
-	    }
-	  target_directory = optarg;
+            target_directory = optarg;
 	  break;
 	case 'T':
 	  no_target_directory = true;
@@ -582,6 +608,16 @@
 				   version_control_string)
 		   : no_backups);
 
+  if(target_directory){
+    add_prefix(destdir, &target_directory);
+    struct stat st;
+    if (stat (target_directory, &st) != 0)
+      error (EXIT_FAILURE, errno, _("accessing %s"), quote (target_directory));
+    if (! S_ISDIR (st.st_mode))
+      error (EXIT_FAILURE, 0, _("target %s is not a directory"),
+             quote (target_directory));
+  }
+
   if (scontext && setfscreatecon (scontext) < 0)
     error (EXIT_FAILURE, errno,
 	   _("failed to set default file creation context to %s"),
@@ -614,8 +650,10 @@
     }
   else if (! (dir_arg || target_directory))
     {
-      if (2 <= n_files && target_directory_operand (file[n_files - 1]))
+      if (2 <= n_files && target_directory_operand (file[n_files - 1])){
 	target_directory = file[--n_files];
+        add_prefix(destdir, &target_directory);
+      }
       else if (2 < n_files)
 	error (EXIT_FAILURE, 0, _("target %s is not a directory"),
 	       quote (file[n_files - 1]));
@@ -656,7 +694,11 @@
   get_ids ();
 
   if (dir_arg)
-    exit_status = savewd_process_files (n_files, file, process_dir, &x);
+    {
+      for(size_t i = 0; i < n_files; i++)
+        add_prefix(destdir, file + i);
+      exit_status = savewd_process_files (n_files, file, process_dir, &x);
+    }
   else
     {
       /* FIXME: it's a little gross that this initialization is
@@ -665,9 +707,11 @@
 
       if (!target_directory)
         {
+          char *target_file = file[1];
+          add_prefix(destdir, &target_file);
           if (! (mkdir_and_install
-		 ? install_file_in_file_parents (file[0], file[1], &x)
-		 : install_file_in_file (file[0], file[1], &x)))
+		 ? install_file_in_file_parents (file[0], target_file, &x)
+		 : install_file_in_file (file[0], target_file, &x)))
 	    exit_status = EXIT_FAILURE;
 	}
       else
@@ -977,6 +1021,8 @@
       fputs (_("\
   -p, --preserve-timestamps   apply access/modification times of SOURCE files\n\
                         to corresponding destination files\n\
+  -P, --destdir[=DESTDIR]       prefix destination with the DESTDIR option or,\n\
+                        if not specified, the DESTDIR environment variable\n\
   -s, --strip         strip symbol tables\n\
       --strip-program=PROGRAM  program used to strip binaries\n\
   -S, --suffix=SUFFIX  override the usual backup suffix\n\
_______________________________________________
Bug-coreutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to