File: clean_temp.c

package info (click to toggle)
grass 6.4.4-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 104,028 kB
  • ctags: 40,409
  • sloc: ansic: 419,980; python: 63,559; tcl: 46,692; cpp: 29,791; sh: 18,564; makefile: 7,000; xml: 3,505; yacc: 561; perl: 559; lex: 480; sed: 70; objc: 7
file content (180 lines) | stat: -rw-r--r-- 4,346 bytes parent folder | download
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
}