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. */
26 #include <stdlib.h> /* For atol() */
30 #include <sys/types.h>
32 #include <ctype.h> /* is_digit() */
34 #include <mhl/memory.h>
35 #include <mhl/string.h>
37 #include "../src/global.h"
38 #include "../src/tty.h" /* enable/disable interrupt key */
39 #include "../src/wtools.h" /* message() */
40 #include "../src/main.h" /* print_vfs_message */
46 #include "../src/panel.h" /* get_current_panel() */
47 #include "../src/layout.h" /* get_current_type() */
50 int vfs_timeout
= 60; /* VFS timeout in seconds */
52 static struct vfs_stamping
*stamps
;
56 vfs_addstamp (struct vfs_class
*v
, vfsid id
)
58 if (!(v
->flags
& VFSF_LOCAL
) && id
!= NULL
) {
59 struct vfs_stamping
*stamp
;
60 struct vfs_stamping
*last_stamp
= NULL
;
62 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
) {
63 if (stamp
->v
== v
&& stamp
->id
== id
) {
64 gettimeofday (&(stamp
->time
), NULL
);
69 stamp
= g_new (struct vfs_stamping
, 1);
73 gettimeofday (&(stamp
->time
), NULL
);
78 last_stamp
->next
= stamp
;
80 /* Add first element */
88 vfs_stamp (struct vfs_class
*v
, vfsid id
)
90 struct vfs_stamping
*stamp
;
92 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
)
93 if (stamp
->v
== v
&& stamp
->id
== id
) {
94 gettimeofday (&(stamp
->time
), NULL
);
101 vfs_rmstamp (struct vfs_class
*v
, vfsid id
)
103 struct vfs_stamping
*stamp
, *st1
;
105 for (stamp
= stamps
, st1
= NULL
; stamp
!= NULL
;
106 st1
= stamp
, stamp
= stamp
->next
)
107 if (stamp
->v
== v
&& stamp
->id
== id
) {
109 stamps
= stamp
->next
;
111 st1
->next
= stamp
->next
;
113 mhl_mem_free (stamp
);
120 /* Find VFS id for given directory name */
122 vfs_getid (struct vfs_class
*vclass
, const char *dir
)
127 /* append slash if needed */
128 dir1
= mhl_str_dir_plus_file (dir
, "");
130 id
= (*vclass
->getid
) (vclass
, dir1
);
138 vfs_stamp_path (char *path
)
140 struct vfs_class
*vfs
;
143 vfs
= vfs_get_class (path
);
144 id
= vfs_getid (vfs
, path
);
145 vfs_addstamp (vfs
, id
);
150 * Create a new timestamp item by VFS class and VFS id.
153 vfs_stamp_create (struct vfs_class
*oldvfs
, vfsid oldvfsid
)
155 struct vfs_class
*nvfs
, *n2vfs
, *n3vfs
;
156 vfsid nvfsid
, n2vfsid
, n3vfsid
;
158 /* There are three directories we have to take care of: current_dir,
159 current_panel->cwd and other_panel->cwd. Athough most of the time either
160 current_dir and current_panel->cwd or current_dir and other_panel->cwd are the
161 same, it's possible that all three are different -- Norbert */
166 nvfs
= vfs_get_class (vfs_get_current_dir ());
167 nvfsid
= vfs_getid (nvfs
, vfs_get_current_dir ());
168 vfs_rmstamp (nvfs
, nvfsid
);
170 if ((nvfs
== oldvfs
&& nvfsid
== oldvfsid
) || oldvfsid
== NULL
) {
174 if (get_current_type () == view_listing
) {
175 n2vfs
= vfs_get_class (current_panel
->cwd
);
176 n2vfsid
= vfs_getid (n2vfs
, current_panel
->cwd
);
177 if (n2vfs
== oldvfs
&& n2vfsid
== oldvfsid
)
184 if (get_other_type () == view_listing
) {
185 n3vfs
= vfs_get_class (other_panel
->cwd
);
186 n3vfsid
= vfs_getid (n3vfs
, other_panel
->cwd
);
187 if (n3vfs
== oldvfs
&& n3vfsid
== oldvfsid
)
194 if (!oldvfs
->nothingisopen
|| !(*oldvfs
->nothingisopen
) (oldvfsid
))
197 vfs_addstamp (oldvfs
, oldvfsid
);
202 vfs_add_current_stamps (void)
204 vfs_stamp_path (vfs_get_current_dir ());
207 if (get_current_type () == view_listing
)
208 vfs_stamp_path (current_panel
->cwd
);
212 if (get_other_type () == view_listing
)
213 vfs_stamp_path (other_panel
->cwd
);
218 /* Compare two timeval structures. Return 0 is t1 is less than t2. */
220 timeoutcmp (struct timeval
*t1
, struct timeval
*t2
)
222 return ((t1
->tv_sec
< t2
->tv_sec
)
223 || ((t1
->tv_sec
== t2
->tv_sec
)
224 && (t1
->tv_usec
<= t2
->tv_usec
)));
228 /* This is called from timeout handler with now = 0, or can be called
229 with now = 1 to force freeing all filesystems that are not in use */
233 static int locked
= 0;
235 struct vfs_stamping
*stamp
, *st
;
237 /* Avoid recursive invocation, e.g. when one of the free functions
243 gettimeofday (&time
, NULL
);
244 time
.tv_sec
-= vfs_timeout
;
246 for (stamp
= stamps
; stamp
!= NULL
;) {
247 if (now
|| (timeoutcmp (&stamp
->time
, &time
))) {
250 (*stamp
->v
->free
) (stamp
->id
);
251 vfs_rmstamp (stamp
->v
, stamp
->id
);
261 * Return the number of seconds remaining to the vfs timeout.
262 * FIXME: The code should be improved to actually return the number of
263 * seconds until the next item times out.
268 return stamps
? 10 : 0;
273 vfs_timeout_handler (void)
280 vfs_release_path (const char *dir
)
282 struct vfs_class
*oldvfs
;
285 oldvfs
= vfs_get_class (dir
);
286 oldvfsid
= vfs_getid (oldvfs
, dir
);
287 vfs_stamp_create (oldvfs
, oldvfsid
);
295 struct vfs_stamping
*stamp
, *st
;
297 for (stamp
= stamps
, stamps
= 0; stamp
!= NULL
;) {
299 (*stamp
->v
->free
) (stamp
->id
);
301 mhl_mem_free (stamp
);
306 vfs_rmstamp (stamps
->v
, stamps
->id
);