-
Notifications
You must be signed in to change notification settings - Fork 9
/
rm_r.c
103 lines (94 loc) · 2.65 KB
/
rm_r.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/***********************************************************************
*
* rm_r.c
*
* Implementation in C of recursive deletion of directory (rm -r dir)
*
* Copyright (C) 2002-2005 Roaring Penguin Software Inc.
* http://www.roaringpenguin.com
*
* This program may be distributed under the terms of the GNU General
* Public License, Version 2.
*
***********************************************************************/
#include "config.h"
#include "mimedefang.h"
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef ENABLE_DEBUGGING
extern void *malloc_debug(void *, size_t, char const *fname, int);
extern char *strdup_debug(void *, char const *, char const *, int);
extern void free_debug(void *, void *, char const *, int);
#undef malloc
#undef strdup
#undef free
#define malloc(x) malloc_debug(ctx, x, __FILE__, __LINE__)
#define strdup(x) strdup_debug(ctx, x, __FILE__, __LINE__)
#define free(x) free_debug(ctx, x, __FILE__, __LINE__)
#define malloc_with_log(x) malloc_debug(ctx, x, __FILE__, __LINE__)
#define strdup_with_log(x) strdup_debug(ctx, x, __FILE__, __LINE__)
#endif
/**********************************************************************
* %FUNCTION: rm_r
* %ARGUMENTS:
* dir -- directory or file name
* %RETURNS:
* -1 on error, 0 otherwise.
* %DESCRIPTION:
* Deletes dir and recursively deletes contents
***********************************************************************/
int
rm_r(char const *qid, char const *dir)
{
char buf[SMALLBUF];
struct stat sbuf;
DIR *d;
struct dirent *entry;
int retcode = 0;
int errno_save;
if (!qid || !*qid) {
qid = "NOQUEUE";
}
if (lstat(dir, &sbuf) < 0) {
syslog(LOG_WARNING, "%s: lstat(%s) failed: %m", qid, dir);
return -1;
}
if (!S_ISDIR(sbuf.st_mode)) {
/* Not a directory - just unlink */
if (unlink(dir) < 0) {
syslog(LOG_WARNING, "%s: unlink(%s) failed: %m", qid, dir);
return -1;
}
return 0;
}
d = opendir(dir);
if (!d) {
errno_save = errno;
syslog(LOG_WARNING, "%s: opendir(%s) failed: %m", qid, dir);
errno = errno_save;
return -1;
}
while((entry = readdir(d)) != NULL) {
if (!strcmp(entry->d_name, ".") ||
!strcmp(entry->d_name, "..")) {
continue;
}
snprintf(buf, sizeof(buf), "%s/%s", dir, entry->d_name);
if (rm_r(qid, buf) < 0) {
retcode = -1;
}
}
closedir(d);
if (rmdir(dir) < 0) {
syslog(LOG_WARNING, "%s: rmdir(%s) failed: %m", qid, dir);
return -1;
}
return retcode;
}