clean_temp.c 4.3 KB

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