GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
clean_temp.c
Go to the documentation of this file.
1#include <grass/config.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <signal.h>
5#include <unistd.h>
6#include <time.h>
7#include <sys/types.h>
8#include <dirent.h>
9#include <sys/stat.h>
10#include <grass/gis.h>
11#include "local_proto.h"
12
13/**************************************************************
14 * clean_temp
15 *
16 * looks for all files in mapset temp directory
17 * of the form pid.n and removes those which have
18 * been abandoned their processes (pid).
19 *
20 * also removes any other file found which is "old"
21 * with an modification time greater then 4 days
22 *
23 * 2006: Rewritten for GRASS 6 by Roberto Flor, ITC-irst
24 *
25 **************************************************************/
26
27#include <limits.h>
28#include <string.h>
29#include <errno.h>
30#ifdef PATH_MAX
31#define BUF_MAX PATH_MAX
32#else
33#define BUF_MAX 4096
34#endif
35
36#define SLEEP 30 /* 30 seconds */
37
38/* Recursively scan the directory pathname, removing directory and files */
39void clean_dir(const char *pathname, uid_t uid, pid_t pid, time_t now,
40 int max_age)
41{
42 char buf[BUF_MAX];
43 DIR *curdir;
44 struct dirent *cur_entry;
45 struct stat info;
46 int n, pathlen;
47
49 if (curdir == NULL) {
50 G_warning("Can't open directory %s: %s,skipping\n", pathname,
52 return;
53 }
54 /* loop over current dir */
55 while ((cur_entry = readdir(curdir))) {
56 if ((G_strcasecmp(cur_entry->d_name, ".") == 0) ||
57 (G_strcasecmp(cur_entry->d_name, "..") == 0))
58 continue; /* Skip dir and parent dir entries */
59
60 if ((pathlen = snprintf(buf, BUF_MAX, "%s/%s", pathname,
61 cur_entry->d_name)) >= BUF_MAX)
62 G_fatal_error("clean_temp: exceeded maximum pathname length %d, "
63 "got %d, shouldn't happen",
65
66 if (stat(buf, &info) != 0) {
67 G_warning("Can't stat file %s: %s,skipping\n", buf,
69 continue;
70 }
71 if (S_ISDIR(info.st_mode)) { /* It's a dir, recurring */
72 clean_dir(buf, uid, pid, now, max_age);
73 /* Return here means we have completed the subdir recursion */
74 /* Trying to remove the now empty dir */
75 if (info.st_uid != uid) /* Not owners of dir */
76 continue;
77#ifndef DEBUG_CLEAN
78 if (rmdir(buf) != 0) {
79 if (errno != ENOTEMPTY) {
80 G_warning("Can't remove empty directory %s: %s,skipping\n",
82 }
83 }
84#else
85 G_warning("Removing directory %s\n", buf);
86#endif
87 }
88 else { /* It's a file check it */
89 if (info.st_uid ==
90 uid) { /* Remove only files owned by current user */
91 if (sscanf(cur_entry->d_name, "%d.%d", &pid, &n) == 2) {
92 if (!find_process(pid))
93#ifndef DEBUG_CLEAN
94 if (unlink(buf) != 0)
95 G_warning("Can't remove file %s: %s,skipping\n",
97#else
98 G_warning("Removing file %s\n", buf);
99#endif
100 }
101 else {
102 if ((now - info.st_mtime) >
103 max_age) /* Not modified in 4 days: TODO configurable
104 param */
105#ifndef DEBUG_CLEAN
106 if (unlink(buf) != 0)
107 G_warning("Can't remove file %s: %s,skipping\n",
108 buf, strerror(errno));
109#else
110 G_warning("Removing file %s\n", buf);
111#endif
112 }
113 }
114 }
115 }
117 return;
118}
119
120int main(int argc, char *argv[])
121{
122 const char *mapset;
123 char element[GNAME_MAX];
124 char tmppath[BUF_MAX];
125 pid_t ppid;
126 pid_t pid;
127 uid_t uid;
128 time_t now;
129 long max_age;
130
131 G_gisinit(argv[0]);
132 pid = 0;
133 ppid = 0;
134 if (argc > 1)
135 sscanf(argv[1], "%d", &ppid);
136
137 /* Get the mapset temp directory */
139 G_file_name(tmppath, element, "", mapset = G_mapset());
140
141 /* get user id and current time in seconds */
142#ifdef _WIN32
143 /* TODO */
144 uid = -1;
145#else
146 uid = getuid();
147#endif
148
149 now = time(NULL);
150
151 /* set maximum age in seconds (4 days) */
152 max_age = 4 * 24 * 60 * 60;
153
154 /*
155 * Scan the temp directory and subdirectory for
156 * files owned by the user and of the form pid.n
157 * to be removed if the process is not running
158 * all "old" files are removed as well
159 */
160
161 while (1) {
162 if (ppid > 0 && !find_process(ppid))
163 break;
164 clean_dir(tmppath, uid, pid, now, max_age);
165 if (ppid <= 0)
166 break;
167 G_sleep(SLEEP);
168 }
169 exit(0);
170}
171
172int find_process(int pid)
173{
174#ifdef _WIN32
175 /* TODO */
176 return -1;
177#else
178 return (kill(pid, 0) == 0 || errno != ESRCH);
179#endif
180}
#define NULL
Definition ccmath.h:32
#define SLEEP
Definition clean_temp.c:36
int find_process(int pid)
Definition clean_temp.c:172
#define BUF_MAX
Definition clean_temp.c:33
void clean_dir(const char *pathname, uid_t uid, pid_t pid, time_t now, int max_age)
Definition clean_temp.c:39
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
void G_temp_element(char *)
Populates element with a path string.
Definition tempfile.c:148
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:61
void G_sleep(unsigned int)
Definition sleep.c:11
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:47
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
struct DIR DIR
Definition dirent.h:18
#define G_gisinit(pgm)
Definition gis.h:71
#define GNAME_MAX
Definition gis.h:196
DIR * opendir(const char *name)
Definition msvc/dirent.c:15
struct dirent * readdir(DIR *dir)
Definition msvc/dirent.c:75
int closedir(DIR *dir)
Definition msvc/dirent.c:54
#define S_ISDIR(mode)
Definition stat.h:6
#define unlink
Definition unistd.h:11
#define rmdir
Definition unistd.h:15
int main(void)
Definition winlocale.c:201