GRASS Programmer's Manual
6.4.2(2012)
|
00001 #include <stdlib.h> 00002 #include <signal.h> 00003 #include <unistd.h> 00004 #include <time.h> 00005 #include <sys/types.h> 00006 #include <dirent.h> 00007 #include <sys/stat.h> 00008 #include <grass/gis.h> 00009 #include "local_proto.h" 00010 00011 /************************************************************** 00012 * clean_temp 00013 * 00014 * looks for all files in mapset temp directory 00015 * of the form pid.n and removes those which have 00016 * been abandoned their processes (pid). 00017 * 00018 * also removes any other file found which is "old" 00019 * with an modification time greater then 4 days 00020 * 00021 * 2006: Rewritten for GRASS 6 by Roberto Flor, ITC-irst 00022 * 00023 **************************************************************/ 00024 00025 #include <limits.h> 00026 #include <string.h> 00027 #include <errno.h> 00028 #ifdef PATH_MAX 00029 #define BUF_MAX PATH_MAX 00030 #else 00031 #define BUF_MAX 4096 00032 #endif 00033 00034 extern int errno; 00035 00036 #define SLEEP 30 /* 30 minutes */ 00037 00038 /* Recursively scan the directory pathname, removing directory and files */ 00039 00040 void clean_dir(const char *pathname, uid_t uid, pid_t pid, time_t now, 00041 int max_age) 00042 { 00043 char buf[BUF_MAX]; 00044 DIR *curdir; 00045 struct dirent *cur_entry; 00046 struct stat info; 00047 int n, pathlen; 00048 00049 curdir = opendir(pathname); 00050 if (curdir == NULL) { 00051 G_warning("Can't open directory %s: %s,skipping\n", pathname, 00052 strerror(errno)); 00053 return; 00054 } 00055 /* loop over current dir */ 00056 while ((cur_entry = readdir(curdir))) { 00057 if ((G_strcasecmp(cur_entry->d_name, ".") == 0) || 00058 (G_strcasecmp(cur_entry->d_name, "..") == 0)) 00059 continue; /* Skip dir and parent dir entries */ 00060 00061 if ((pathlen = 00062 G_snprintf(buf, BUF_MAX, "%s/%s", pathname, 00063 cur_entry->d_name)) >= BUF_MAX) 00064 G_fatal_error 00065 ("clean_temp: exceeded maximum pathname length %d, got %d, should'nt happen", 00066 BUF_MAX, pathlen); 00067 00068 if (stat(buf, &info) != 0) { 00069 G_warning("Can't stat file %s: %s,skipping\n", buf, 00070 strerror(errno)); 00071 continue; 00072 } 00073 if (S_ISDIR(info.st_mode)) { /* It's a dir, recurring */ 00074 clean_dir(buf, uid, pid, now, max_age); 00075 /* Return here means we have completed the subdir recursion */ 00076 /* Trying to remove the now empty dir */ 00077 if (info.st_uid != uid) /* Not owners of dir */ 00078 continue; 00079 #ifndef DEBUG_CLEAN 00080 if (rmdir(buf) != 0) { 00081 if (errno != ENOTEMPTY) { 00082 G_warning 00083 ("Can't remove empty directory %s: %s,skipping\n", 00084 buf, strerror(errno)); 00085 } 00086 } 00087 #else 00088 G_warning("Removing directory %s\n", buf); 00089 #endif 00090 } 00091 else { /* It's a file check it */ 00092 if (info.st_uid == uid) { /* Remove only files owned by current user */ 00093 if (sscanf(cur_entry->d_name, "%d.%d", &pid, &n) == 2) { 00094 if (!find_process(pid)) 00095 #ifndef DEBUG_CLEAN 00096 if (unlink(buf) != 0) 00097 G_warning("Can't remove file %s: %s,skipping\n", 00098 buf, strerror(errno)); 00099 #else 00100 G_warning("Removing file %s\n", buf); 00101 #endif 00102 } 00103 else { 00104 if ((now - info.st_mtime) > max_age) /* Not modified in 4 days: TODO configurable param */ 00105 #ifndef DEBUG_CLEAN 00106 if (unlink(buf) != 0) 00107 G_warning("Can't remove file %s: %s,skipping\n", 00108 buf, strerror(errno)); 00109 #else 00110 G_warning("Removing file %s\n", buf); 00111 #endif 00112 } 00113 } 00114 } 00115 } 00116 closedir(curdir); 00117 return; 00118 } 00119 00120 int main(int argc, char *argv[]) 00121 { 00122 char *mapset; 00123 char element[GNAME_MAX]; 00124 char tmppath[BUF_MAX]; 00125 pid_t ppid; 00126 pid_t pid; 00127 uid_t uid; 00128 time_t now; 00129 long max_age; 00130 00131 G_gisinit(argv[0]); 00132 pid = 0; 00133 ppid = 0; 00134 if (argc > 1) 00135 sscanf(argv[1], "%d", &ppid); 00136 00137 /* Get the mapset temp directory */ 00138 G__temp_element(element); 00139 G__file_name(tmppath, element, "", mapset = G_mapset()); 00140 00141 /* get user id and current time in seconds */ 00142 #ifdef __MINGW32__ 00143 /* TODO */ 00144 uid = -1; 00145 #else 00146 uid = getuid(); 00147 #endif 00148 00149 now = time(NULL); 00150 00151 /* set maximum age in seconds (4 days) */ 00152 max_age = 4 * 24 * 60 * 60; 00153 00154 /* 00155 * Scan the temp directory and subdirectory for 00156 * files owned by the user and of the form pid.n 00157 * to be removed if the process is not running 00158 * all "old" files are removed as well 00159 */ 00160 00161 while (1) { 00162 if (ppid > 0 && !find_process(ppid)) 00163 break; 00164 clean_dir(tmppath, uid, pid, now, max_age); 00165 if (ppid <= 0) 00166 break; 00167 G_sleep(SLEEP); 00168 } 00169 exit(0); 00170 } 00171 00172 int find_process(int pid) 00173 { 00174 #ifdef __MINGW32__ 00175 /* TODO */ 00176 return -1; 00177 #else 00178 return (kill(pid, 0) == 0 || errno != ESRCH); 00179 #endif 00180 }