Module Name:    othersrc
Committed By:   stacktic
Date:           Thu Apr  2 07:48:35 UTC 2009

Modified Files:
        othersrc/bin/fsu_ecp: fsu_ecp.c

Log Message:
Added hardlink support


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 othersrc/bin/fsu_ecp/fsu_ecp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: othersrc/bin/fsu_ecp/fsu_ecp.c
diff -u othersrc/bin/fsu_ecp/fsu_ecp.c:1.2 othersrc/bin/fsu_ecp/fsu_ecp.c:1.3
--- othersrc/bin/fsu_ecp/fsu_ecp.c:1.2	Fri Mar 27 10:33:53 2009
+++ othersrc/bin/fsu_ecp/fsu_ecp.c	Thu Apr  2 07:48:35 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: fsu_ecp.c,v 1.2 2009/03/27 10:33:53 pooka Exp $ */
+/* $NetBSD: fsu_ecp.c,v 1.3 2009/04/02 07:48:35 stacktic Exp $ */
 
 /*
  * Copyright (c) 2008 Arnaud Ysmal.  All Rights Reserved.
@@ -58,6 +58,8 @@
 static int copy_dir_rec(struct ukfs *, const char *, char *, int);
 static int copy_fifo(struct ukfs *, const char *, const char *, int);
 static int copy_file(struct ukfs *, const char *, const char *, int);
+static int copy_filein(struct ukfs *, const char *, const char *);
+static int copy_fileout(const char *, const char *);
 static int copy_link(struct ukfs *, const char *, const char *, int);
 static int copy_special(struct ukfs *, const char *, const char *, int);
 static int copy_to_dir(struct ukfs *, const char *, struct stat *,
@@ -68,6 +70,12 @@
 static int fsu_ecp_parse_arg(int *, char ***);
 static void usage(void);
 
+struct hardlink_s {
+	char *hl_from;
+	char *hl_to;
+	struct hardlink_s *next;
+};
+
 int
 main(int argc, char *argv[])
 {
@@ -171,11 +179,6 @@
 	if (rv == 0 && S_ISDIR(to_stat.st_mode))
 		return copy_to_dir(fs, from, &from_stat, to, flags);
 
-	if (from_stat.st_ino == to_stat.st_ino) {
-		fprintf(stderr, "%s and %s are identical (not copied).\n",
-			from, to);
-		return -1;
-	}
 	return copy_to_file(fs, from, &from_stat, to, flags);
 }
 
@@ -205,9 +208,7 @@
 			if (filename == NULL)
 				filename = from;
 			else {
-				printf("filename = \"%s\"\n", filename);
 				if (filename[1] == '\0') {
-					printf("brdl\n");
 					for (rv = strlen(from) - 2;
 					     rv >= 0 && from[rv] != '/';
 					     --rv)
@@ -245,11 +246,15 @@
 static int
 copy_dir_rec(struct ukfs *fs, const char *from_p, char *to_p, int flags)
 {
-	FSU_FENT *root, *cur;
+	FSU_FENT *root, *cur, *cur2, *tmp;
 	size_t len;
-	int flist_options, res, rv, off;
+	int flist_options, res, rv, off, hl_supported;
+	struct hardlink_s *hl_l, *last, *new;
+	char hlfrom[PATH_MAX + 1], hlto[PATH_MAX + 1];
 
+	hl_l = last = NULL;
 	res = 0;
+	hl_supported = 1;
 
 	if (flags & FSU_ECP_COPY_LINK)
 		flist_options = FSU_FLIST_STATLINK;
@@ -268,6 +273,40 @@
 
 	if (root == NULL)
 		return -1;
+
+	off = root->pathlen;
+	for (cur = root->next; cur != NULL; cur = cur->next) {
+		if (cur->sb.st_nlink == 1)
+			continue;
+		for (cur2 = cur; cur2->next != NULL;) {
+			if (cur2->next->sb.st_nlink == 1) {
+				cur2 = cur2->next;
+				continue;
+			}
+			if (cur->sb.st_ino == cur2->next->sb.st_ino &&
+			    cur->sb.st_dev == cur2->next->sb.st_dev) {
+				new = malloc(sizeof(struct hardlink_s));
+				if (new == NULL) {
+					warn("malloc");
+					return -1;
+				}
+				new->hl_from = strdup(cur->path);
+				new->hl_to = strdup(cur2->next->path);
+				new->next = NULL;
+				
+				if (hl_l == NULL)
+					hl_l = last = new;
+				else 
+					last = last->next = new;
+				tmp = cur2->next;
+				cur2->next = cur2->next->next;
+				fsu_flist_free_entry(tmp);
+				if (cur->sb.st_nlink == 2)
+					break;
+			} else
+				cur2 = cur2->next;
+		}
+	}
 	
 	if (flags & FSU_ECP_GET)
 		rv = mkdir(to_p, root->sb.st_mode);
@@ -285,8 +324,6 @@
 		}
 	}
 
-	off = root->pathlen;
-
 	for (cur = root->next; cur != NULL; cur = cur->next) {
 		
 		rv = strlcat(to_p, cur->path + off, PATH_MAX+1);
@@ -328,7 +365,38 @@
 		}
 		to_p[len + 1] = '\0';
 	}
-	
+
+	while ((new = hl_l) != NULL) {
+		hl_l = hl_l->next;
+		
+		memcpy(hlfrom, to_p, len + 1);
+		memcpy(hlto, to_p, len + 1);
+		hlfrom[len + 1] = '\0';
+		hlto[len + 1] = '\0';
+			
+		strlcat(hlfrom, new->hl_from + off, PATH_MAX+1);
+		strlcat(hlto, new->hl_to + off, PATH_MAX+1);
+		
+		if (hl_supported) {
+			if (flags & FSU_ECP_GET)
+				rv = link(hlfrom, hlto);
+			else
+				rv = ukfs_link(fs, hlfrom, hlto);
+			if (rv != 0 && errno == EOPNOTSUPP) {
+				hl_supported = 0;
+				copy_filein(fs, hlfrom, hlto);
+			}
+		} else {
+			if (flags & FSU_ECP_GET)
+				copy_fileout(hlfrom, hlto);
+			else
+				copy_filein(fs, hlfrom, hlto);	
+		}
+
+		free(new->hl_from);
+		free(new->hl_to);
+		free(new);
+	}
 out:
 	fsu_flist_free(root);
 
@@ -602,6 +670,93 @@
 	return 0;
 }
 
+static int
+copy_filein(struct ukfs *fs, const char *from, const char *to)
+{
+	uint8_t buf[BUFSIZE];
+	ssize_t rd, wr;
+	off_t off;
+	int rv;
+	struct stat from_stat;
+
+	rv = ukfs_stat(fs, from, &from_stat);
+	if (rv == -1) {
+		warn("%s", from);
+		return -1;
+	}
+
+	rv = ukfs_create(fs, to, from_stat.st_mode);
+	if (rv == -1) {
+		warn("%s", to);
+		return -1;
+	}
+	
+	off = 0;
+	do {
+		rd = ukfs_read(fs, from, off, buf, BUFSIZE);
+		if (rd == -1) {
+			warn("%s", from);
+			return -1;
+		}
+		wr = ukfs_write(fs, to, off, buf, rd);
+		if (wr == -1 || wr != rd) {
+			warn("%s", to);
+			return -1;
+		}
+		off += rd;
+	} while (rd == BUFSIZE);
+
+	return 0;
+}
+
+static int
+copy_fileout(const char *from, const char *to)
+{
+	uint8_t buf[BUFSIZE];
+	ssize_t rd, wr;
+	int rv, fdfrom, fdto;
+	struct stat from_stat;
+
+	rv = stat(from, &from_stat);
+	if (rv == -1) {
+		warn("%s", from);
+		return -1;
+	}
+
+	fdto = open(to, O_CREAT | O_WRONLY, from_stat.st_mode);
+	if (fdto == -1) {
+		warn("%s", to);
+		return -1;
+	}
+	fdfrom = open(to, O_RDONLY, from_stat.st_mode);
+	if (fdfrom == -1) {
+		warn("%s", to);
+		close(fdto);
+		return -1;
+	}
+
+	do {
+		rd = read(fdfrom, buf, BUFSIZE);
+		if (rd == -1) {
+			warn("%s", from);
+			rv = -1;
+			goto out;
+		}
+		wr = write(fdto, buf, rd);
+		if (wr == -1 || wr != rd) {
+			warn("%s", to);
+			rv = -1;
+			goto out;
+		}
+	} while (rd == BUFSIZE);
+
+
+out:
+	close(fdfrom);
+	close(fdto);
+	return rv;
+}
+
 static void
 usage(void)
 {

Reply via email to