summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/file.c
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2007-01-19 23:23:22 +0000
committerJoris Vink <joris@cvs.openbsd.org>2007-01-19 23:23:22 +0000
commit4a71af5c4d11fdae042f2ba1627067246f58fa88 (patch)
tree9a90929604a6c8676d72aa8a00d480cb4af286d4 /usr.bin/cvs/file.c
parentdc6e8ac5f69a36e3db19a40d55c2797148813cfb (diff)
When we hit a DT_UNKNOWN for dirent->d_type in our filelist functions,
stat() the filepath to get the correct type, and therefor add it to the appropriate list. This fixes opencvs with CVSROOTs on NFS and AFS, because they both return D_UNKNOWN for directories (afs even for files too) in dirent->d_type. problem found by thib@ and todd@ tested by thib@, todd@, ok niallo@
Diffstat (limited to 'usr.bin/cvs/file.c')
-rw-r--r--usr.bin/cvs/file.c62
1 files changed, 48 insertions, 14 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;
}