/* * remove_dir.c - Part of AFD, an automatic file distribution program. * Copyright (c) 2000 - 2022 Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** remove_dir - removes one directory with all its files ** ** SYNOPSIS ** int remove_dir(char *dirname, int wait_time) ** ** DESCRIPTION ** Deletes the directory 'dirname' with all its files. If there ** are directories within this directory the function will fail. ** For this purpose rather use the function rec_rmdir(). ** ** RETURN VALUES ** Returns INCORRECT when it fails to delete the directory. Or ** FILE_IS_DIR is returned when there are directories in 'dirname'. ** When successful it will return 0. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 10.12.2000 H.Kiehl Created ** 10.07.2002 H.Kiehl Return FILE_IS_DIR when there are directories ** in dirname. ** */ DESCR__E_M3 #include #include /* strcpy(), strlen() */ #include /* rmdir(), unlink() */ #include #ifdef HAVE_STATX # include /* Definition of AT_* constants */ #endif #include /* stat() */ #include /* opendir(), readdir(), closedir() */ #include /*############################# remove_dir() ############################*/ int #ifdef WITH_UNLINK_DELAY remove_dir(char *dirname, int wait_time) #else remove_dir(char *dirname) #endif { int addchar = NO; #ifdef WITH_UNLINK_DELAY int loops = 0; #endif char *ptr; struct dirent *dirp; DIR *dp; #ifdef WITH_UNLINK_DELAY try_again2: #endif ptr = dirname + strlen(dirname); if ((dp = opendir(dirname)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to opendir() `%s' : %s"), dirname, strerror(errno)); return(INCORRECT); } if (*(ptr - 1) != '/') { *(ptr++) = '/'; addchar = YES; } while ((dirp = readdir(dp)) != NULL) { if ((dirp->d_name[0] == '.') && ((dirp->d_name[1] == '\0') || ((dirp->d_name[1] == '.') && (dirp->d_name[2] == '\0')))) { continue; } #ifdef LINUX if (dirp->d_type == DT_DIR) { (void)closedir(dp); if (addchar == YES) { ptr[-1] = 0; } else { *ptr = '\0'; } return(FILE_IS_DIR); } #endif (void)strcpy(ptr, dirp->d_name); #ifdef WITH_UNLINK_DELAY try_again: #endif if (unlink(dirname) == -1) { if (errno == ENOENT) { #ifdef WITH_UNLINK_DELAY if (loops == 0) { #endif system_log(DEBUG_SIGN, __FILE__, __LINE__, _("Failed to delete `%s' : %s"), dirname, strerror(errno)); #ifdef WITH_UNLINK_DELAY } #endif } #ifdef EISDIR else if (errno == EISDIR) { (void)closedir(dp); if (addchar == YES) { ptr[-1] = 0; } else { *ptr = '\0'; } return(FILE_IS_DIR); } #endif #ifdef WITH_UNLINK_DELAY else if ((errno == EBUSY) && (wait_time > 0) && (loops < (10 * wait_time))) { (void)my_usleep(100000L); loops++; goto try_again; } #endif else { int ret = INCORRECT, save_errno = errno; if (errno == EPERM) { #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif #ifdef HAVE_STATX if (statx(0, dirname, AT_STATX_SYNC_AS_STAT, STATX_MODE, &stat_buf) == -1) #else if (stat(dirname, &stat_buf) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX _("Failed to statx() `%s' : %s"), #else _("Failed to stat() `%s' : %s"), #endif dirname, strerror(errno)); } else { #ifdef HAVE_STATX if (S_ISDIR(stat_buf.stx_mode)) #else if (S_ISDIR(stat_buf.st_mode)) #endif { ret = FILE_IS_DIR; } } } system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to delete `%s' : %s"), dirname, strerror(save_errno)); (void)closedir(dp); if (addchar == YES) { ptr[-1] = 0; } else { *ptr = '\0'; } return(ret); } } } if (addchar == YES) { ptr[-1] = 0; } else { *ptr = '\0'; } if (closedir(dp) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to closedir() `%s' : %s"), dirname, strerror(errno)); return(INCORRECT); } if (rmdir(dirname) == -1) { #ifdef WITH_UNLINK_DELAY if ((errno == ENOTEMPTY) && (wait_time > 0) && (loops < (10 * wait_time))) { (void)my_usleep(100000L); loops++; goto try_again2; } #endif system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to delete directory `%s' with rmdir() : %s"), dirname, strerror(errno)); return(INCORRECT); } return(SUCCESS); }