[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [BusyBox] busybox tar - test script & patch for handling of hard links...
From:       Jim Gleason <jimg () lineo ! com>
Date:       2000-11-28 15:16:35
[Download RAW message or body]

Hey all, attached are two files dealing with busybox tar.  I have sent
these before but no one has indicated they have tested them or even
care.  Would someone mind having a look.

tar_tests.bash -> A test script that thouroughly test tar (busybox VS
GNU).  This would go in the tests sub-directory.

tar.c.hardlink.patch -> A patch that fixes the busybox tar utility to
correctly handle hard links.
This patch was made for tar.c revision number 1.70 and tar.c is now up
to 1.72, but the patch should still work.

Thanks,
Jim Gleason
["tar_tests.bash" (application/octet-stream)]
["tar.c.hardlink.patch" (application/octet-stream)]

Index: tar.c
===================================================================
RCS file: /var/cvs/busybox/tar.c,v
retrieving revision 1.70
diff -u -b -B -p -r1.70 tar.c
--- tar.c	2000/11/08 02:35:47	1.70
+++ tar.c	2000/11/10 00:57:25
@@ -720,6 +721,21 @@ endgame:
 
 #ifdef BB_FEATURE_TAR_CREATE
 
+/*
+** writeTarFile(),  writeFileToTarball(), and writeTarHeader() are
+** the only functions that deal with the HardLinkInfo structure.
+** Even these functions use the xxxHardLinkInfo() functions.
+*/
+typedef struct HardLinkInfo HardLinkInfo;
+struct HardLinkInfo
+{
+	HardLinkInfo *next;           /* Next entry in list */
+	dev_t dev;                    /* Device number */
+	ino_t ino;                    /* Inode number */
+	short linkCount;              /* (Hard) Link Count */
+	char name[1];                 /* Start of filename (must be last) */
+};
+
 /* Some info to be carried along when creating a new tarball */
 struct TarBallInfo
 {
@@ -732,10 +748,59 @@ struct TarBallInfo
 									 to include the tarball into itself */
 	int verboseFlag;              /* Whether to print extra stuff or not */
 	char** excludeList;           /* List of files to not include */
+	HardLinkInfo *hlInfoHead;     /* Hard Link Tracking Information */
+	HardLinkInfo *hlInfo;         /* Hard Link Info for the current file */
 };
 typedef struct TarBallInfo TarBallInfo;
 
 
+/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
+static void
+addHardLinkInfo (HardLinkInfo **hlInfoHeadPtr, dev_t dev, ino_t ino,
+		short linkCount, const char *name)
+{
+	/* Note: hlInfoHeadPtr can never be NULL! */
+	HardLinkInfo *hlInfo;
+
+	hlInfo = (HardLinkInfo *)xmalloc(sizeof(HardLinkInfo)+strlen(name)+1);
+	if (hlInfo) {
+		hlInfo->next = *hlInfoHeadPtr;
+		*hlInfoHeadPtr = hlInfo;
+		hlInfo->dev = dev;
+		hlInfo->ino = ino;
+		hlInfo->linkCount = linkCount;
+		strcpy(hlInfo->name, name);
+	}
+	return;
+}
+
+static void
+freeHardLinkInfo (HardLinkInfo **hlInfoHeadPtr)
+{
+	/* Note: hlInfoHeadPtr can never be NULL! */
+	HardLinkInfo *hlInfo = *hlInfoHeadPtr;
+	HardLinkInfo *hlInfoNext = NULL;
+
+	while(hlInfo) {
+		hlInfoNext = hlInfo->next;
+		free(hlInfo);
+	}
+	*hlInfoHeadPtr = NULL;
+	return;
+}
+
+/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
+static HardLinkInfo *
+findHardLinkInfo (HardLinkInfo *hlInfo, dev_t dev, ino_t ino)
+{
+	while(hlInfo) {
+		if ((ino == hlInfo->ino) && (dev == hlInfo->dev))
+			break;
+		hlInfo = hlInfo->next;
+	}
+	return(hlInfo);
+}
+
 /* Put an octal string into the specified buffer.
  * The number is zero and space padded and possibly null padded.
  * Returns TRUE if successful.  */ 
@@ -830,8 +895,11 @@ writeTarHeader(struct TarBallInfo *tbInf
 	if (! *header.uname)
 		strcpy(header.uname, "root");
 
-	/* WARNING/NOTICE: I break Hard Links */
-	if (S_ISLNK(statbuf->st_mode)) {
+	if (tbInfo->hlInfo) {
+		/* This is a hard link */
+		header.typeflag = LNKTYPE;
+		strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname));
+	} else if (S_ISLNK(statbuf->st_mode)) {
 		int link_size=0;
 		char buffer[BUFSIZ];
 		header.typeflag  = SYMTYPE;
@@ -899,6 +967,22 @@ static int writeFileToTarball(const char
 {
 	struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
 
+	/*
+	** Check to see if we are dealing with a hard link.
+	** If so -
+	** Treat the first occurance of a given dev/inode as a file while
+	** treating any additional occurances as hard links.  This is done
+	** by adding the file information to the HardLinkInfo linked list.
+	*/
+	tbInfo->hlInfo = NULL;
+	if (statbuf->st_nlink > 1) {
+		tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf->st_dev, 
+				statbuf->st_ino);
+		if (tbInfo->hlInfo == NULL)
+			addHardLinkInfo (&tbInfo->hlInfoHead, statbuf->st_dev,
+					statbuf->st_ino, statbuf->st_nlink, fileName);
+	}
+
 	/* It is against the rules to archive a socket */
 	if (S_ISSOCK(statbuf->st_mode)) {
 		errorMsg("%s: socket ignored\n", fileName);
@@ -924,7 +1008,8 @@ static int writeFileToTarball(const char
 	} 
 
 	/* Now, if the file is a regular file, copy it out to the tarball */
-	if (S_ISREG(statbuf->st_mode)) {
+	if ((tbInfo->hlInfo == NULL)
+	&&  (S_ISREG(statbuf->st_mode))) {
 		int  inputFileFd;
 		char buffer[BUFSIZ];
 		ssize_t size=0, readSize=0;
@@ -966,6 +1051,7 @@ static int writeTarFile(const char* tarN
 	ssize_t size;
 	struct TarBallInfo tbInfo;
 	tbInfo.verboseFlag = verboseFlag;
+	tbInfo.hlInfoHead = NULL;
 
 	/* Make sure there is at least one file to tar up.  */
 	if (*argv == NULL)
@@ -978,6 +1064,7 @@ static int writeTarFile(const char* tarN
 		tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 	if (tbInfo.tarFd < 0) {
 		errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno));
+		freeHardLinkInfo(&tbInfo.hlInfoHead);
 		return ( FALSE);
 	}
 	tbInfo.excludeList=excludeList;
@@ -1012,8 +1099,10 @@ static int writeTarFile(const char* tarN
 	close(tarFd);
 	if (errorFlag == TRUE) {
 		errorMsg("Error exit delayed from previous errors\n");
+		freeHardLinkInfo(&tbInfo.hlInfoHead);
 		return(FALSE);
 	}
+	freeHardLinkInfo(&tbInfo.hlInfoHead);
 	return( TRUE);
 }
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic