diff options
author | Joris Vink <joris@cvs.openbsd.org> | 2007-01-19 23:23:22 +0000 |
---|---|---|
committer | Joris Vink <joris@cvs.openbsd.org> | 2007-01-19 23:23:22 +0000 |
commit | 4a71af5c4d11fdae042f2ba1627067246f58fa88 (patch) | |
tree | 9a90929604a6c8676d72aa8a00d480cb4af286d4 /usr.bin/cvs/file.c | |
parent | dc6e8ac5f69a36e3db19a40d55c2797148813cfb (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.c | 62 |
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; } |