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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <grass/gis.h>
#include "local_proto.h"
/**************************************************************
* clean_temp
*
* looks for all files in mapset temp directory
* of the form pid.n and removes those which have
* been abandoned their processes (pid).
*
* also removes any other file found which is "old"
* with an modification time greater then 4 days
*
* 2006: Rewritten for GRASS 6 by Roberto Flor, ITC-irst
*
**************************************************************/
#include <limits.h>
#include <string.h>
#include <errno.h>
#ifdef PATH_MAX
#define BUF_MAX PATH_MAX
#else
#define BUF_MAX 4096
#endif
extern int errno;
#define SLEEP 30 /* 30 seconds */
/* Recursively scan the directory pathname, removing directory and files */
void clean_dir(const char *pathname, uid_t uid, pid_t pid, time_t now,
int max_age)
{
char buf[BUF_MAX];
DIR *curdir;
struct dirent *cur_entry;
struct stat info;
int n, pathlen;
curdir = opendir(pathname);
if (curdir == NULL) {
G_warning("Can't open directory %s: %s,skipping\n", pathname,
strerror(errno));
return;
}
/* loop over current dir */
while ((cur_entry = readdir(curdir))) {
if ((G_strcasecmp(cur_entry->d_name, ".") == 0) ||
(G_strcasecmp(cur_entry->d_name, "..") == 0))
continue; /* Skip dir and parent dir entries */
if ((pathlen =
G_snprintf(buf, BUF_MAX, "%s/%s", pathname,
cur_entry->d_name)) >= BUF_MAX)
G_fatal_error
("clean_temp: exceeded maximum pathname length %d, got %d, should'nt happen",
BUF_MAX, pathlen);
if (stat(buf, &info) != 0) {
G_warning("Can't stat file %s: %s,skipping\n", buf,
strerror(errno));
continue;
}
if (S_ISDIR(info.st_mode)) { /* It's a dir, recurring */
clean_dir(buf, uid, pid, now, max_age);
/* Return here means we have completed the subdir recursion */
/* Trying to remove the now empty dir */
if (info.st_uid != uid) /* Not owners of dir */
continue;
#ifndef DEBUG_CLEAN
if (rmdir(buf) != 0) {
if (errno != ENOTEMPTY) {
G_warning
("Can't remove empty directory %s: %s,skipping\n",
buf, strerror(errno));
}
}
#else
G_warning("Removing directory %s\n", buf);
#endif
}
else { /* It's a file check it */
if (info.st_uid == uid) { /* Remove only files owned by current user */
if (sscanf(cur_entry->d_name, "%d.%d", &pid, &n) == 2) {
if (!find_process(pid))
#ifndef DEBUG_CLEAN
if (unlink(buf) != 0)
G_warning("Can't remove file %s: %s,skipping\n",
buf, strerror(errno));
#else
G_warning("Removing file %s\n", buf);
#endif
}
else {
if ((now - info.st_mtime) > max_age) /* Not modified in 4 days: TODO configurable param */
#ifndef DEBUG_CLEAN
if (unlink(buf) != 0)
G_warning("Can't remove file %s: %s,skipping\n",
buf, strerror(errno));
#else
G_warning("Removing file %s\n", buf);
#endif
}
}
}
}
closedir(curdir);
return;
}
int main(int argc, char *argv[])
{
char *mapset;
char element[GNAME_MAX];
char tmppath[BUF_MAX];
pid_t ppid;
pid_t pid;
uid_t uid;
time_t now;
long max_age;
G_gisinit(argv[0]);
pid = 0;
ppid = 0;
if (argc > 1)
sscanf(argv[1], "%d", &ppid);
/* Get the mapset temp directory */
G__temp_element(element);
G__file_name(tmppath, element, "", mapset = G_mapset());
/* get user id and current time in seconds */
#ifdef __MINGW32__
/* TODO */
uid = -1;
#else
uid = getuid();
#endif
now = time(NULL);
/* set maximum age in seconds (4 days) */
max_age = 4 * 24 * 60 * 60;
/*
* Scan the temp directory and subdirectory for
* files owned by the user and of the form pid.n
* to be removed if the process is not running
* all "old" files are removed as well
*/
while (1) {
if (ppid > 0 && !find_process(ppid))
break;
clean_dir(tmppath, uid, pid, now, max_age);
if (ppid <= 0)
break;
G_sleep(SLEEP);
}
exit(0);
}
int find_process(int pid)
{
#ifdef __MINGW32__
/* TODO */
return -1;
#else
return (kill(pid, 0) == 0 || errno != ESRCH);
#endif
}
|