src/fuse/udcFuse/udcFuse.c 1.7
1.7 2010/01/05 00:39:06 angie
Make empty directory appear to be non-existent, so udcFuse doesn't get confused by an empty dir becoming a regular file (i.e. udcCache dir with bitmap and sparseData).
Index: src/fuse/udcFuse/udcFuse.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/fuse/udcFuse/udcFuse.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -b -B -U 4 -r1.6 -r1.7
--- src/fuse/udcFuse/udcFuse.c 20 Nov 2009 17:56:35 -0000 1.6
+++ src/fuse/udcFuse/udcFuse.c 5 Jan 2010 00:39:06 -0000 1.7
@@ -88,18 +88,28 @@
if (dirHandle != NULL)
{
// should we make sure that there are not also subdirectories??
boolean gotBitmap = FALSE, gotSparse = FALSE;
+ int isEmpty = TRUE;
struct dirent *dirInfo;
while ((dirInfo = readdir(dirHandle)) != NULL)
{
+ if (sameString(dirInfo->d_name, ".") || sameString(dirInfo->d_name, ".."))
+ continue;
+ isEmpty = FALSE;
if (sameString(dirInfo->d_name, "bitmap"))
gotBitmap = TRUE;
else if (sameString(dirInfo->d_name, "sparseData"))
gotSparse = TRUE;
if (gotBitmap && gotSparse)
break;
}
+ // fuse gets confused when a cache path is an empty dir, and then suddenly morphs
+ // into a regular file, as happens when old cache files are removed by the
+ // trash cleaner but then reappear due to a new udc access. So if empty dir,
+ // just tell fuse that it doesn't exist.
+ if (isEmpty)
+ return -ENOENT;
if (gotBitmap || gotSparse)
{
if (gotBitmap ^ gotSparse)
fprintf(stderr, "...[%d] getattr: got one cache file but not the other - stale?\n",
@@ -186,8 +196,33 @@
fprintf(stderr, "...[%d] getattr %s finish %ld\n", pid, path, clock1000());
return ret;
}
+static boolean isEmptyDir(char *udcCachePath, char *subdir)
+/* Return TRUE if subdir of path is a directory with no children. */
+{
+boolean isDir = FALSE, isEmpty = TRUE;
+char fullPath[4096];
+ERR_CATCH_START();
+safef(fullPath, sizeof(fullPath), "%s/%s", udcCachePath, subdir);
+ERR_CATCH_END("safef fullPath");
+DIR *dirHandle = opendir(fullPath);
+if (dirHandle != NULL)
+ {
+ isDir = TRUE;
+ struct dirent *dirInfo;
+ while ((dirInfo = readdir(dirHandle)) != NULL)
+ {
+ if (sameString(dirInfo->d_name, ".") || sameString(dirInfo->d_name, ".."))
+ continue;
+ isEmpty = FALSE;
+ break;
+ }
+ closedir(dirHandle);
+ }
+return isDir && isEmpty;
+}
+
static int udcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
/* Read the corresponding udc cache directory. */
{
@@ -203,10 +238,17 @@
return -errno;
}
struct dirent *dirInfo;
while ((dirInfo = readdir(dirHandle)) != NULL)
+ // getattr denies the existence of empty udcCache directories because they
+ // might get bitmap and sparseData files and then we report them as regular
+ // files not directories. Filter out components here that are empty directories:
+ if (sameString(".", dirInfo->d_name) || sameString("..", dirInfo->d_name) ||
+ !isEmptyDir(udcCachePath, dirInfo->d_name))
+ {
if (filler(buf, dirInfo->d_name, NULL, 0))
break;
+ }
int ret = closedir(dirHandle);
fprintf(stderr, "...[%d] readdir %s finish %ld\n", pid, path, clock1000());
return ret;
}