summaryrefslogtreecommitdiff
path: root/usr.bin
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
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')
-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);
}