Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Use (hard) linking instead of copying, when possible [patch] #21

Closed
michaelrsweet opened this issue Nov 17, 2009 · 3 comments
Closed

Use (hard) linking instead of copying, when possible [patch] #21

michaelrsweet opened this issue Nov 17, 2009 · 3 comments
Milestone

Comments

@michaelrsweet
Copy link
Owner

Version: 4.x-feature
Original reporter:

The patch below should help large projects (such as OpenOffice) save a lot of I/O time and disk-space during packaging.

It changes the copy_file function to attempt to use link(2) first, and only proceed to the actual copying of the files, if link fails for any reason.

@michaelrsweet
Copy link
Owner Author

"patch-link":

Change copy_file() function to try to create a hard link instead
of copying...

	-mi

--- file.c	2006-08-29 12:43:09.000000000 -0400
+++ file.c	2009-11-16 19:49:06.242283000 -0500
@@ -67,4 +67,17 @@
 
   unlink(dst);
+  if (link(src, dst) == 0)
+  {
+    if (Verbosity > 1)
+       printf("Successfully linked %s to %s instead of copying\n",
+              src, dst);
+    return 0;
+  }
+  else
+  {
+    if (Verbosity > 1)
+       printf("Linking %s to %s failed: %s.\n\tFalling back to copying\n",
+              src, dst, strerror(errno));
+  }
 
   if ((dstfile = fopen(dst, "wb")) == NULL)

@michaelrsweet
Copy link
Owner Author

Original reporter: Michael Sweet

OK, I've implemented this slightly differently; basically, I've updated both copy_file and make_directory to support both optional mode/owner/group and copy_file to try doing a hard link when the mode/owner/group either match the requested values or are optional. The mode/owner/group stuff is needed for Debian and Solaris packages but not for RPM packages, so the speedup will only be applied when safe to do so.

See attached patch.

@michaelrsweet
Copy link
Owner Author

"str21.patch":

Index: file.c
===================================================================
--- file.c	(revision 839)
+++ file.c	(working copy)
@@ -49,6 +49,7 @@
   char		buffer[8192];		/* Copy buffer */
   char		*slash;			/* Pointer to trailing slash */
   size_t	bytes;			/* Number of bytes read/written */
+  struct stat	srcinfo;		/* Source file information */
 
 
  /*
@@ -63,11 +64,22 @@
     make_directory(buffer, 0755, owner, group);
 
  /*
-  * Open files...
+  * Try doing a hard link instead of a copy...
   */
 
   unlink(dst);
 
+  if (!stat(src, &srcinfo) &&
+      (!mode || srcinfo.st_mode == mode) &&
+      (owner == (uid_t)-1 || srcinfo.st_uid == owner) &&
+      (group == (gid_t)-1 || srcinfo.st_gid == group) &&
+      !link(src, dst))
+    return (0);
+
+ /*
+  * Open files...
+  */
+
   if ((dstfile = fopen(dst, "wb")) == NULL)
   {
     fprintf(stderr, "epm: Unable to create \"%s\" -\n     %s\n", dst,
@@ -109,8 +121,10 @@
   fclose(srcfile);
   fclose(dstfile);
 
-  chmod(dst, mode);
-  chown(dst, owner, group);
+  if (mode)
+    chmod(dst, mode);
+  if (owner != (uid_t)-1 && group != (gid_t)-1)
+    chown(dst, owner, group);
 
   return (0);
 }
@@ -138,9 +152,11 @@
 
       if (access(buffer, F_OK))
       {
-	mkdir(buffer, 0777);
-	chmod(buffer, mode | 0700);
-	chown(buffer, owner, group);
+	mkdir(buffer, 0755);
+	if (mode)
+          chmod(buffer, mode | 0700);
+	if (owner != (uid_t)-1 && group != (gid_t)-1)
+	  chown(buffer, owner, group);
       }
     }
 
@@ -151,9 +167,11 @@
 
   if (access(buffer, F_OK))
   {
-    mkdir(buffer, 0777);
-    chmod(buffer, mode | 0700);
-    chown(buffer, owner, group);
+    mkdir(buffer, 0755);
+    if (mode)
+      chmod(buffer, mode | 0700);
+    if (owner != (uid_t)-1 && group != (gid_t)-1)
+      chown(buffer, owner, group);
   }
 
   return (0);
Index: rpm.c
===================================================================
--- rpm.c	(revision 839)
+++ rpm.c	(working copy)
@@ -63,8 +63,6 @@
   char		name[1024],		/* Product filename */
 		filename[1024];		/* Destination filename */
   file_t	*file;			/* Current distribution file */
-  struct passwd	*pwd;			/* Pointer to user record */
-  struct group	*grp;			/* Pointer to group record */
   char		absdir[1024];		/* Absolute directory */
   char		rpmdir[1024];		/* RPMDIR env var */
   char		release[256];		/* Release: number */
@@ -178,16 +176,6 @@
   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
   {
    /*
-    * Find the username and groupname IDs...
-    */
-
-    pwd = getpwnam(file->user);
-    grp = getgrnam(file->group);
-
-    endpwent();
-    endgrent();
-
-   /*
     * Copy the file or make the directory or make the symlink as needed...
     */
 
@@ -200,8 +188,7 @@
 	  if (Verbosity > 1)
 	    printf("%s -> %s...\n", file->src, filename);
 
-	  if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0,
-			grp ? grp->gr_gid : 0))
+	  if (copy_file(filename, file->src, 0, -1, -1))
 	    return (1);
           break;
       case 'i' :
@@ -215,8 +202,7 @@
 	  if (Verbosity > 1)
 	    printf("%s -> %s...\n", file->src, filename);
 
-	  if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0,
-			grp ? grp->gr_gid : 0))
+	  if (copy_file(filename, file->src, 0, -1, -1))
 	    return (1);
           break;
       case 'd' :
@@ -225,8 +211,7 @@
 	  if (Verbosity > 1)
 	    printf("Directory %s...\n", filename);
 
-          make_directory(filename, file->mode, pwd ? pwd->pw_uid : 0,
-			 grp ? grp->gr_gid : 0);
+          make_directory(filename, 0755, -1, -1);
           break;
       case 'l' :
           snprintf(filename, sizeof(filename), "%s/buildroot%s", directory, file->dst);

@michaelrsweet michaelrsweet added this to the Stable milestone Mar 3, 2017
michaelrsweet added a commit that referenced this issue Oct 11, 2017
…n for

copies, as current versions of RPM do not support such things (Issue #57)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant