summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cvs/file.c62
-rw-r--r--usr.bin/cvs/repository.c65
2 files changed, 103 insertions, 24 deletions
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index e3d3fb7d5e4..a9aa1e3922a 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.170 2007/01/14 23:10:56 joris Exp $ */
+/* $OpenBSD: file.c,v 1.171 2007/01/19 23:23:21 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -342,7 +342,7 @@ next:
void
cvs_file_walkdir(struct cvs_file *cf, struct cvs_recursion *cr)
{
- int l;
+ int l, type;
FILE *fp;
int nbytes;
size_t len;
@@ -438,27 +438,61 @@ cvs_file_walkdir(struct cvs_file *cf, struct cvs_recursion *cr)
continue;
}
- if (!(cr->flags & CR_RECURSE_DIRS) &&
- dp->d_type == DT_DIR) {
- cp += dp->d_reclen;
- continue;
- }
-
l = snprintf(fpath, MAXPATHLEN, "%s/%s",
cf->file_path, dp->d_name);
if (l == -1 || l >= MAXPATHLEN)
fatal("cvs_file_walkdir: overflow");
/*
- * Anticipate the file type to sort them,
- * note that we do not determine the final
- * type until we actually have the fd floating
- * around.
+ * nfs and afs will show d_type as DT_UNKNOWN
+ * for files and/or directories so when we encounter
+ * this we call stat() on the path to be sure.
*/
- if (dp->d_type == DT_DIR)
+ if (dp->d_type == DT_UNKNOWN) {
+ if (stat(fpath, &st) == -1)
+ fatal("'%s': %s", fpath,
+ strerror(errno));
+
+ switch (st.st_mode & S_IFMT) {
+ case S_IFDIR:
+ type = CVS_DIR;
+ break;
+ case S_IFREG:
+ type = CVS_FILE;
+ break;
+ default:
+ fatal("Unknown file type in copy");
+ }
+ } else {
+ switch (dp->d_type) {
+ case DT_DIR:
+ type = CVS_DIR;
+ break;
+ case DT_REG:
+ type = CVS_FILE;
+ break;
+ default:
+ fatal("Unknown file type in copy");
+ }
+ }
+
+ if (!(cr->flags & CR_RECURSE_DIRS) &&
+ type == CVS_DIR) {
+ cp += dp->d_reclen;
+ continue;
+ }
+
+ switch (type) {
+ case CVS_DIR:
cvs_file_get(fpath, &dl);
- else if (dp->d_type == DT_REG)
+ break;
+ case CVS_FILE:
cvs_file_get(fpath, &fl);
+ break;
+ default:
+ fatal("type %d unknown, shouldn't happen",
+ type);
+ }
cp += dp->d_reclen;
}
diff --git a/usr.bin/cvs/repository.c b/usr.bin/cvs/repository.c
index d2cd6958903..2ff62dc3434 100644
--- a/usr.bin/cvs/repository.c
+++ b/usr.bin/cvs/repository.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: repository.c,v 1.7 2006/12/11 07:59:18 xsa Exp $ */
+/* $OpenBSD: repository.c,v 1.8 2007/01/19 23:23:21 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -89,9 +89,14 @@ void
cvs_repository_getdir(const char *dir, const char *wdir,
struct cvs_flisthead *fl, struct cvs_flisthead *dl, int dodirs)
{
+ int type;
DIR *dirp;
+ struct stat st;
struct dirent *dp;
- char *s, fpath[MAXPATHLEN];
+ char *s, *fpath, *rpath;
+
+ rpath = xmalloc(MAXPATHLEN);
+ fpath = xmalloc(MAXPATHLEN);
if ((dirp = opendir(dir)) == NULL)
fatal("cvs_repository_getdir: failed to open '%s'", dir);
@@ -106,25 +111,65 @@ cvs_repository_getdir(const char *dir, const char *wdir,
if (cvs_file_chkign(dp->d_name))
continue;
- if (dodirs == 0 && dp->d_type == DT_DIR)
- continue;
-
if (cvs_path_cat(wdir, dp->d_name,
- fpath, sizeof(fpath)) >= sizeof(fpath))
+ fpath, MAXPATHLEN) >= MAXPATHLEN)
+ fatal("cvs_repository_getdir: truncation");
+
+ if (cvs_path_cat(dir, dp->d_name,
+ rpath, MAXPATHLEN) >= MAXPATHLEN)
fatal("cvs_repository_getdir: truncation");
/*
- * Anticipate the file type for sorting, we do not determine
- * the final file type until we have the fd floating around.
+ * nfs and afs will show d_type as DT_UNKNOWN
+ * for files and/or directories so when we encounter
+ * this we call stat() on the path to be sure.
*/
- if (dp->d_type == DT_DIR) {
+ if (dp->d_type == DT_UNKNOWN) {
+ if (stat(rpath, &st) == -1)
+ fatal("'%s': %s", rpath, strerror(errno));
+
+ switch (st.st_mode & S_IFMT) {
+ case S_IFDIR:
+ type = CVS_DIR;
+ break;
+ case S_IFREG:
+ type = CVS_FILE;
+ break;
+ default:
+ fatal("Unknown file type in repository");
+ }
+ } else {
+ switch (dp->d_type) {
+ case DT_DIR:
+ type = CVS_DIR;
+ break;
+ case DT_REG:
+ type = CVS_FILE;
+ break;
+ default:
+ fatal("Unknown file type in repository");
+ }
+ }
+
+ if (dodirs == 0 && type == CVS_DIR)
+ continue;
+
+ switch (type) {
+ case CVS_DIR:
cvs_file_get(fpath, dl);
- } else if (dp->d_type == DT_REG) {
+ break;
+ case CVS_FILE:
if ((s = strrchr(fpath, ',')) != NULL)
*s = '\0';
cvs_file_get(fpath, fl);
+ break;
+ default:
+ fatal("type %d unknown, shouldn't happen", type);
}
}
+ xfree(rpath);
+ xfree(fpath);
+
(void)closedir(dirp);
}