static int _removeIncompleteCaches(const char *path) { DIR *dir = opendir(path); char filepath[MAX_NAME_LEN]; struct dirent *entry; struct stat statbuf; int filenameLen; int extLen; int status; int statusFailed = 0; if (dir != NULL) { while ((entry = readdir(dir)) != NULL) { if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { continue; } snprintf(filepath, MAX_NAME_LEN, "%s/%s", path, entry->d_name); if (!stat(filepath, &statbuf)) { // has entry if (S_ISDIR(statbuf.st_mode)) { // directory status = _removeIncompleteCaches(filepath); if (status < 0) { statusFailed = status; } if (isEmptyDir(filepath) == 0) { rodsLog (LOG_DEBUG, "_removeIncompleteCaches: removing empty dir : %s", filepath); status = rmdir(filepath); if (status < 0) { statusFailed = status; } } } else { // file filenameLen = strlen(entry->d_name); extLen = strlen(PRELOAD_FILES_IN_DOWNLOADING_EXT); if (filenameLen > extLen && !strcmp(entry->d_name + filenameLen - extLen, PRELOAD_FILES_IN_DOWNLOADING_EXT)) { // found incomplete cache rodsLog (LOG_DEBUG, "_removeIncompleteCaches: removing incomplete cache : %s", filepath); status = unlink(filepath); if (status < 0) { statusFailed = status; } } } } } closedir(dir); } return statusFailed; }
int my_rmdir(int argc, char* argv[]) { result_t result = NONE; const int uid = running->uid; const int device = running->cwd->device; if(argc < 2) { fprintf(stderr, "rmdir: missing operand\n"); return MISSING_OPERAND; } // rmdir each path given by user int i = 1; while(i < argc) { char* path = argv[i]; int ino = getino(device, path); MINODE* mip = iget(device, ino); // Verify file exists if(!mip) { result = DOES_NOT_EXIST; fprintf(stderr, "rmdir: failed to remove '%s':" " No such file or directory\n", path); goto clean_up; } // Verify user has permission to remove the directory else if(uid != SUPER_USER && uid != mip->inode.i_uid) { result = PERM_DENIED; fprintf(stderr, "rmdir: failed to remove '%s':" " Permission denied\n", path); goto clean_up; } // Verify that it is a directory else if(!S_ISDIR(mip->inode.i_mode)) { result = NOT_DIR; fprintf(stderr, "rmdir: failed to remove '%s':" " Not a directory\n", path); goto clean_up; } // Verify that it is not busy else if(mip->refCount > 1) { result = BUSY; fprintf(stderr, "rmdir: failed to remove directory '%s':" " Directory busy\n", path); goto clean_up; } // Verify that it is empty else if(!isEmptyDir(mip)) { result = NOT_EMPTY; fprintf(stderr, "rmdir: failed to remove directory '%s':" " Directory not empty\n", path); goto clean_up; } // If removing multiple directories, display if(argc > 2) printf("rmdir: removing directory '%s'\n", path); INODE* ip = &mip->inode; // Get parent DIR's ino and Minode int parent_ino = 0; findino(mip, &ino, &parent_ino); MINODE* parent_mip = iget(device, parent_ino); INODE* parent_ip = &parent_mip->inode; // Deallocate its blocks for(int b = 0; b < NUM_DIRECT_BLOCKS && ip->i_block[b] != 0; b++) bfree(device, ip->i_block[b]); // Deallocate its inode ifree(device, ino); // Remove entry from parent directory rm_child(parent_mip, ino); // Update parent's info parent_ip->i_links_count--; parent_ip->i_atime = time(0L); parent_ip->i_mtime = time(0L); parent_mip->dirty = true; // Write parent changes to disk iput(parent_mip); clean_up: // Write changes to deleted directory to disk and clear refCount iput(mip); if(result != NONE) return result; i++; } return SUCCESS; }