summaryrefslogtreecommitdiff
path: root/utils/lndir
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2007-07-30 22:31:52 +0000
committerIan Lynagh <igloo@earth.li>2007-07-30 22:31:52 +0000
commitf74a6116eb089646eec41755eccbe0eb88a99ac0 (patch)
treee81f7f9030e92c33c0e083b4ab0ccb0524ffbd7a /utils/lndir
parentdefcdb005b2257162871579964d7a4d585ffd020 (diff)
downloadhaskell-f74a6116eb089646eec41755eccbe0eb88a99ac0.tar.gz
Make lndir work on Windows (by copying)
Diffstat (limited to 'utils/lndir')
-rw-r--r--utils/lndir/lndir.c100
1 files changed, 91 insertions, 9 deletions
diff --git a/utils/lndir/lndir.c b/utils/lndir/lndir.c
index 813e4e094d..6cc240a978 100644
--- a/utils/lndir/lndir.c
+++ b/utils/lndir/lndir.c
@@ -82,6 +82,7 @@ in this Software without prior written authorization from the X Consortium.
extern int errno;
#endif
int silent = 0; /* -silent */
+int copy = 0; /* -copy */
int ignore_links = 0; /* -ignorelinks */
char *rcurdir;
@@ -89,6 +90,17 @@ char *curdir;
int force=0;
+#ifdef WIN32
+#define mymkdir(X, Y) mkdir(X)
+#else
+#define mymkdir(X, Y) mkdir(X, Y)
+#endif
+
+#ifndef WIN32
+#define SYMLINKS
+#define BELIEVE_ST_NLINK
+#endif
+
void
quit (
#if NeedVarargsPrototypes
@@ -155,6 +167,58 @@ mperror (s)
perror (s);
}
+#define BUFSIZE 1024
+int copyfile(const char *oldpath, const char *newpath) {
+ FILE *f_old;
+ FILE *f_new;
+ int e;
+ ssize_t s;
+ char buf[BUFSIZE];
+
+#ifdef SYMLINKS
+ if (copy) {
+ return symlink(oldpath, newpath);
+ } else {
+#endif
+ f_old = fopen(oldpath, "rb");
+ if (f_old == NULL) {
+ return -1;
+ }
+ f_new = fopen(newpath, "wbx");
+ if (f_new == NULL) {
+ e = errno;
+ fclose(f_old);
+ errno = e;
+ return -1;
+ }
+ while ((s = fread(buf, 1, BUFSIZE, f_old)) > 0) {
+ if (fwrite(buf, 1, s, f_new) < s) {
+ e = errno;
+ fclose(f_old);
+ fclose(f_new);
+ errno = e;
+ return -1;
+ }
+ }
+ if (!feof(f_old)) {
+ e = errno;
+ fclose(f_old);
+ fclose(f_new);
+ errno = e;
+ return -1;
+ }
+ if (fclose(f_new) == EOF) {
+ e = errno;
+ fclose(f_old);
+ errno = e;
+ return -1;
+ }
+ fclose(f_old);
+ return 0;
+#ifdef SYMLINKS
+ }
+#endif
+}
int equivalent(lname, rname)
char *lname;
@@ -188,11 +252,15 @@ int rel; /* if true, prepend "../" to fn before using */
char basesym[MAXPATHLEN + 1];
struct stat sb, sc;
int n_dirs;
- int symlen;
+ int symlen = -1;
int basesymlen = -1;
char *ocurdir;
- if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
+ if ((fs->st_dev == ts->st_dev) &&
+ (fs->st_ino == ts->st_ino) &&
+ /* inode is always 0 on Windows; we don't want to fail in that case */
+ (fs->st_ino != 0)
+ ) {
msg ("%s: From and to directories are identical!", fn);
return 1;
}
@@ -218,7 +286,15 @@ int rel; /* if true, prepend "../" to fn before using */
continue;
strcpy (p, dp->d_name);
- if (n_dirs > 0) {
+ if (
+#ifdef BELIEVE_ST_NLINK
+ n_dirs > 0
+#else
+ /* st_nlink is 1 on Windows, so we have to keep looking for
+ * directories forever */
+ 1
+#endif
+ ) {
if (stat (buf, &sb) < 0) {
mperror (buf);
continue;
@@ -256,24 +332,27 @@ int rel; /* if true, prepend "../" to fn before using */
if (!silent)
printf ("%s:\n", buf);
if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
- if (mkdir (dp->d_name, 0777) < 0 ||
+ if (mymkdir (dp->d_name, 0777) < 0 ||
stat (dp->d_name, &sc) < 0) {
mperror (dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
}
+#ifdef SYMLINKS
if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
msg ("%s: is a link instead of a directory", dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
+#endif
if (chdir (dp->d_name) < 0) {
mperror (dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
- dodir (buf, &sb, &sc, (buf[0] != '/'));
+ rel = (fn[0] != '/') && ((fn[0] == '\0') || (fn[1] != ':'));
+ dodir (buf, &sb, &sc, rel);
if (chdir ("..") < 0)
quiterr (1, "..");
curdir = rcurdir = ocurdir;
@@ -282,6 +361,7 @@ int rel; /* if true, prepend "../" to fn before using */
}
/* non-directory */
+#ifdef SYMLINKS
symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
if (symlen >= 0)
symbuf[symlen] = '\0';
@@ -295,12 +375,13 @@ int rel; /* if true, prepend "../" to fn before using */
if (basesymlen >= 0)
basesym[basesymlen] = '\0';
}
+#endif
if (symlen >= 0) {
if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf)) {
if (force) {
unlink(dp->d_name);
- if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
+ if (copyfile (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
mperror (dp->d_name);
} else {
/* Link exists in new tree. Print message if it doesn't match. */
@@ -308,7 +389,7 @@ int rel; /* if true, prepend "../" to fn before using */
}
}
} else {
- if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
+ if (copyfile (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
mperror (dp->d_name);
}
}
@@ -317,7 +398,6 @@ int rel; /* if true, prepend "../" to fn before using */
return 0;
}
-
main (ac, av)
int ac;
char **av;
@@ -345,6 +425,8 @@ char **av;
force = 1;
else if (strcmp(*av, "-ignorelinks") == 0)
ignore_links = 1;
+ else if (strcmp(*av, "-copy") == 0)
+ copy = 1;
else if (strcmp(*av, "--") == 0) {
++av, --ac;
break;
@@ -370,7 +452,7 @@ char **av;
/* to directory */
if (stat (tn, &ts) < 0) {
if (force && (tn[0] != '.' || tn[1] != '\0') ) {
- mkdir(tn, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
+ mymkdir(tn, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
}
else {
quiterr (1, tn);