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)
{