static int do_recursive_delete(const char *d, const char *file, uint8_t delfiles, int32_t name_max) { int ret=RECDEL_ERROR; DIR *dirp=NULL; struct dirent *entry=NULL; struct dirent *result; struct stat statp; char *directory=NULL; char *fullpath=NULL; if(!file) { if(!(directory=prepend_s(d, ""))) goto end; } else if(!(directory=prepend_s(d, file))) { log_out_of_memory(__func__); goto end; } if(lstat(directory, &statp)) { // path does not exist. ret=RECDEL_OK; goto end; } if(!(dirp=opendir(directory))) { logp("opendir %s: %s\n", directory, strerror(errno)); goto end; } if(!(entry=(struct dirent *) malloc_w(sizeof(struct dirent)+name_max+100, __func__))) goto end; while(1) { if(readdir_r(dirp, entry, &result) || !result) { // Got to the end of the directory. ret=RECDEL_OK; break; } if(!entry->d_ino || !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; free_w(&fullpath); if(!(fullpath=prepend_s(directory, entry->d_name))) goto end; if(is_dir(fullpath, entry)>0) { int r; if((r=do_recursive_delete(directory, entry->d_name, delfiles, name_max))==RECDEL_ERROR) goto end; // do not overwrite ret with OK if it previously // had ENTRIES_REMAINING if(r==RECDEL_ENTRIES_REMAINING) ret=r; } else if(delfiles) { if(unlink(fullpath)) { logp("unlink %s: %s\n", fullpath, strerror(errno)); ret=RECDEL_ENTRIES_REMAINING; } } else { ret=RECDEL_ENTRIES_REMAINING; } } if(ret==RECDEL_OK && rmdir(directory)) { logp("rmdir %s: %s\n", directory, strerror(errno)); ret=RECDEL_ERROR; } end: if(dirp) closedir(dirp); free_w(&fullpath); free_w(&directory); free_v((void **)&entry); return ret; }
static int do_recursive_delete_w(const char *path, uint8_t delfiles) { int32_t name_max; get_max(&name_max, _PC_NAME_MAX); return do_recursive_delete(path, NULL, delfiles, name_max); }
int recursive_delete(const char *d, const char *file, uint8_t delfiles) { int32_t name_max; get_max(&name_max, _PC_NAME_MAX); return do_recursive_delete(d, file, delfiles, name_max); }