static void bpc_attribCache_destroyEntry(bpc_attribCache_dir *attr) { bpc_attrib_dirDestroy(&attr->dir); }
/* * Remove all the files below path (if a directory) and path itself. Deduct reference counts * for every attrib file removed. * * Note that inodes are *not* updated, even in cases where nlinks > 0. */ int bpc_path_remove(char *path, int compress) { char filePath[BPC_MAXPATHLEN]; STRUCT_STAT st; DIR *dir; struct dirent *dp; int errorCnt = 0; size_t dirListSize = 0, dirListLen = 0; char *dirList = NULL, *dirListP; if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_remove(%s)\n", path); if ( !(dir = opendir(path)) ) { unlink(path); return errorCnt; } while ( (dp = readdir(dir)) ) { if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue; snprintf(filePath, sizeof(filePath), "%s/%s", path, dp->d_name); if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_remove: removing %s\n", filePath); if ( stat(filePath, &st) ) { /* * hmmm. stat failed - just try to remove it */ unlink(filePath); continue; } if ( S_ISDIR(st.st_mode) ) { /* * To avoid recursing with dir still open (consuming an open fd), remember all the dirs * and recurse after we close dir. */ if ( !dirList ) { dirListSize = 4096; if ( !(dirList = malloc(dirListSize)) ) { bpc_logErrf("bpc_path_refCountAll: can't allocate %u bytes\n", (unsigned)dirListSize); return ++errorCnt; } } if ( dirListLen + strlen(dp->d_name) + 1 >= dirListSize ) { dirListSize = dirListSize * 2 + strlen(dp->d_name); if ( !(dirList = realloc(dirList, dirListSize)) ) { bpc_logErrf("bpc_path_refCountAll: can't reallocate %u bytes\n", (unsigned)dirListSize); return ++errorCnt; } } strcpy(dirList + dirListLen, dp->d_name); dirListLen += strlen(dp->d_name) + 1; } else { /* * if this is an attrib file, we need to read it and deduct the reference counts. */ if ( !strncmp(dp->d_name, "attrib", 6) ) { bpc_attrib_dir dir; bpc_attrib_dirInit(&dir, compress); if ( bpc_attrib_dirRead(&dir, NULL, filePath, 0) ) { bpc_logErrf("bpc_path_remove: can't read attrib file %s\n", filePath); errorCnt++; } if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_remove: adjusting ref counts from attrib file %s\n", filePath); if ( !unlink(filePath) ) { /* * Only reduce the ref counts if we succeeded in removing the attrib file */ bpc_attrib_dirRefCount(&dir, -1); } bpc_attrib_dirDestroy(&dir); } else { if ( unlink(filePath) ) errorCnt++; } } } closedir(dir); /* * Now visit the subdirs we have saved above. */ if ( dirList ) { for ( dirListP = dirList ; dirListP < dirList + dirListLen ; dirListP += strlen(dirListP) + 1 ) { snprintf(filePath, sizeof(filePath), "%s/%s", path, dirListP); errorCnt += bpc_path_remove(filePath, compress); } free(dirList); } if ( rmdir(path) ) errorCnt++; return errorCnt; }