1 /* Virtual File System garbage collection code
2 Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 Written by: 1995 Miguel de Icaza
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License
11 as published by the Free Software Foundation; either version 2 of
12 the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 * \brief Source: Virtual File System: garbage collection code
26 * \author Miguel de Icaza
27 * \author Jakub Jelinek
28 * \author Pavel Machek
29 * \author Pavel Roskin
30 * \date 1995, 1998, 2003
37 #include <stdlib.h> /* For atol() */
41 #include <sys/types.h>
42 #include <ctype.h> /* is_digit() */
43 #include <sys/time.h> /* gettimeofday() */
45 #include "../src/global.h"
47 #include "../src/wtools.h" /* message() */
48 #include "../src/main.h" /* print_vfs_message */
49 #include "../src/panel.h" /* get_current_panel() */
50 #include "../src/layout.h" /* get_current_type() */
58 int vfs_timeout
= 60; /* VFS timeout in seconds */
60 static struct vfs_stamping
*stamps
;
64 vfs_addstamp (struct vfs_class
*v
, vfsid id
)
66 if (!(v
->flags
& VFSF_LOCAL
) && id
!= NULL
) {
67 struct vfs_stamping
*stamp
;
68 struct vfs_stamping
*last_stamp
= NULL
;
70 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
) {
71 if (stamp
->v
== v
&& stamp
->id
== id
) {
72 gettimeofday (&(stamp
->time
), NULL
);
77 stamp
= g_new (struct vfs_stamping
, 1);
81 gettimeofday (&(stamp
->time
), NULL
);
86 last_stamp
->next
= stamp
;
88 /* Add first element */
96 vfs_stamp (struct vfs_class
*v
, vfsid id
)
98 struct vfs_stamping
*stamp
;
100 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
)
101 if (stamp
->v
== v
&& stamp
->id
== id
) {
102 gettimeofday (&(stamp
->time
), NULL
);
109 vfs_rmstamp (struct vfs_class
*v
, vfsid id
)
111 struct vfs_stamping
*stamp
, *st1
;
113 for (stamp
= stamps
, st1
= NULL
; stamp
!= NULL
;
114 st1
= stamp
, stamp
= stamp
->next
)
115 if (stamp
->v
== v
&& stamp
->id
== id
) {
117 stamps
= stamp
->next
;
119 st1
->next
= stamp
->next
;
128 /* Find VFS id for given directory name */
130 vfs_getid (struct vfs_class
*vclass
, const char *dir
)
135 /* append slash if needed */
136 dir1
= concat_dir_and_file (dir
, "");
138 id
= (*vclass
->getid
) (vclass
, dir1
);
146 vfs_stamp_path (char *path
)
148 struct vfs_class
*vfs
;
151 vfs
= vfs_get_class (path
);
152 id
= vfs_getid (vfs
, path
);
153 vfs_addstamp (vfs
, id
);
158 * Create a new timestamp item by VFS class and VFS id.
161 vfs_stamp_create (struct vfs_class
*oldvfs
, vfsid oldvfsid
)
163 struct vfs_class
*nvfs
, *n2vfs
, *n3vfs
;
164 vfsid nvfsid
, n2vfsid
, n3vfsid
;
166 /* There are three directories we have to take care of: current_dir,
167 current_panel->cwd and other_panel->cwd. Athough most of the time either
168 current_dir and current_panel->cwd or current_dir and other_panel->cwd are the
169 same, it's possible that all three are different -- Norbert */
174 nvfs
= vfs_get_class (vfs_get_current_dir ());
175 nvfsid
= vfs_getid (nvfs
, vfs_get_current_dir ());
176 vfs_rmstamp (nvfs
, nvfsid
);
178 if ((nvfs
== oldvfs
&& nvfsid
== oldvfsid
) || oldvfsid
== NULL
) {
182 if (get_current_type () == view_listing
) {
183 n2vfs
= vfs_get_class (current_panel
->cwd
);
184 n2vfsid
= vfs_getid (n2vfs
, current_panel
->cwd
);
185 if (n2vfs
== oldvfs
&& n2vfsid
== oldvfsid
)
192 if (get_other_type () == view_listing
) {
193 n3vfs
= vfs_get_class (other_panel
->cwd
);
194 n3vfsid
= vfs_getid (n3vfs
, other_panel
->cwd
);
195 if (n3vfs
== oldvfs
&& n3vfsid
== oldvfsid
)
202 if (!oldvfs
->nothingisopen
|| !(*oldvfs
->nothingisopen
) (oldvfsid
))
205 vfs_addstamp (oldvfs
, oldvfsid
);
210 vfs_add_current_stamps (void)
212 vfs_stamp_path (vfs_get_current_dir ());
215 if (get_current_type () == view_listing
)
216 vfs_stamp_path (current_panel
->cwd
);
220 if (get_other_type () == view_listing
)
221 vfs_stamp_path (other_panel
->cwd
);
226 /* Compare two timeval structures. Return 0 is t1 is less than t2. */
228 timeoutcmp (struct timeval
*t1
, struct timeval
*t2
)
230 return ((t1
->tv_sec
< t2
->tv_sec
)
231 || ((t1
->tv_sec
== t2
->tv_sec
)
232 && (t1
->tv_usec
<= t2
->tv_usec
)));
236 /* This is called from timeout handler with now = 0, or can be called
237 with now = 1 to force freeing all filesystems that are not in use */
241 static int locked
= 0;
242 struct timeval lc_time
;
243 struct vfs_stamping
*stamp
, *st
;
245 /* Avoid recursive invocation, e.g. when one of the free functions
251 gettimeofday (&lc_time
, NULL
);
252 lc_time
.tv_sec
-= vfs_timeout
;
254 for (stamp
= stamps
; stamp
!= NULL
;) {
255 if (now
|| (timeoutcmp (&stamp
->time
, &lc_time
))) {
258 (*stamp
->v
->free
) (stamp
->id
);
259 vfs_rmstamp (stamp
->v
, stamp
->id
);
269 * Return the number of seconds remaining to the vfs timeout.
270 * FIXME: The code should be improved to actually return the number of
271 * seconds until the next item times out.
276 return stamps
? 10 : 0;
281 vfs_timeout_handler (void)
288 vfs_release_path (const char *dir
)
290 struct vfs_class
*oldvfs
;
293 oldvfs
= vfs_get_class (dir
);
294 oldvfsid
= vfs_getid (oldvfs
, dir
);
295 vfs_stamp_create (oldvfs
, oldvfsid
);
303 struct vfs_stamping
*stamp
, *st
;
305 for (stamp
= stamps
, stamps
= 0; stamp
!= NULL
;) {
307 (*stamp
->v
->free
) (stamp
->id
);
314 vfs_rmstamp (stamps
->v
, stamps
->id
);