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/string.h>
36 #include "../src/global.h"
37 #include "../src/tty.h" /* enable/disable interrupt key */
38 #include "../src/wtools.h" /* message() */
39 #include "../src/main.h" /* print_vfs_message */
45 #include "../src/panel.h" /* get_current_panel() */
46 #include "../src/layout.h" /* get_current_type() */
49 int vfs_timeout
= 60; /* VFS timeout in seconds */
51 static struct vfs_stamping
*stamps
;
55 vfs_addstamp (struct vfs_class
*v
, vfsid id
)
57 if (!(v
->flags
& VFSF_LOCAL
) && id
!= NULL
) {
58 struct vfs_stamping
*stamp
;
59 struct vfs_stamping
*last_stamp
= NULL
;
61 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
) {
62 if (stamp
->v
== v
&& stamp
->id
== id
) {
63 gettimeofday (&(stamp
->time
), NULL
);
68 stamp
= g_new (struct vfs_stamping
, 1);
72 gettimeofday (&(stamp
->time
), NULL
);
77 last_stamp
->next
= stamp
;
79 /* Add first element */
87 vfs_stamp (struct vfs_class
*v
, vfsid id
)
89 struct vfs_stamping
*stamp
;
91 for (stamp
= stamps
; stamp
!= NULL
; stamp
= stamp
->next
)
92 if (stamp
->v
== v
&& stamp
->id
== id
) {
93 gettimeofday (&(stamp
->time
), NULL
);
100 vfs_rmstamp (struct vfs_class
*v
, vfsid id
)
102 struct vfs_stamping
*stamp
, *st1
;
104 for (stamp
= stamps
, st1
= NULL
; stamp
!= NULL
;
105 st1
= stamp
, stamp
= stamp
->next
)
106 if (stamp
->v
== v
&& stamp
->id
== id
) {
108 stamps
= stamp
->next
;
110 st1
->next
= stamp
->next
;
119 /* Find VFS id for given directory name */
121 vfs_getid (struct vfs_class
*vclass
, const char *dir
)
126 /* append slash if needed */
127 dir1
= mhl_str_dir_plus_file (dir
, "");
129 id
= (*vclass
->getid
) (vclass
, dir1
);
137 vfs_stamp_path (char *path
)
139 struct vfs_class
*vfs
;
142 vfs
= vfs_get_class (path
);
143 id
= vfs_getid (vfs
, path
);
144 vfs_addstamp (vfs
, id
);
149 * Create a new timestamp item by VFS class and VFS id.
152 vfs_stamp_create (struct vfs_class
*oldvfs
, vfsid oldvfsid
)
154 struct vfs_class
*nvfs
, *n2vfs
, *n3vfs
;
155 vfsid nvfsid
, n2vfsid
, n3vfsid
;
157 /* There are three directories we have to take care of: current_dir,
158 current_panel->cwd and other_panel->cwd. Athough most of the time either
159 current_dir and current_panel->cwd or current_dir and other_panel->cwd are the
160 same, it's possible that all three are different -- Norbert */
165 nvfs
= vfs_get_class (vfs_get_current_dir ());
166 nvfsid
= vfs_getid (nvfs
, vfs_get_current_dir ());
167 vfs_rmstamp (nvfs
, nvfsid
);
169 if ((nvfs
== oldvfs
&& nvfsid
== oldvfsid
) || oldvfsid
== NULL
) {
173 if (get_current_type () == view_listing
) {
174 n2vfs
= vfs_get_class (current_panel
->cwd
);
175 n2vfsid
= vfs_getid (n2vfs
, current_panel
->cwd
);
176 if (n2vfs
== oldvfs
&& n2vfsid
== oldvfsid
)
183 if (get_other_type () == view_listing
) {
184 n3vfs
= vfs_get_class (other_panel
->cwd
);
185 n3vfsid
= vfs_getid (n3vfs
, other_panel
->cwd
);
186 if (n3vfs
== oldvfs
&& n3vfsid
== oldvfsid
)
193 if (!oldvfs
->nothingisopen
|| !(*oldvfs
->nothingisopen
) (oldvfsid
))
196 vfs_addstamp (oldvfs
, oldvfsid
);
201 vfs_add_current_stamps (void)
203 vfs_stamp_path (vfs_get_current_dir ());
206 if (get_current_type () == view_listing
)
207 vfs_stamp_path (current_panel
->cwd
);
211 if (get_other_type () == view_listing
)
212 vfs_stamp_path (other_panel
->cwd
);
217 /* Compare two timeval structures. Return 0 is t1 is less than t2. */
219 timeoutcmp (struct timeval
*t1
, struct timeval
*t2
)
221 return ((t1
->tv_sec
< t2
->tv_sec
)
222 || ((t1
->tv_sec
== t2
->tv_sec
)
223 && (t1
->tv_usec
<= t2
->tv_usec
)));
227 /* This is called from timeout handler with now = 0, or can be called
228 with now = 1 to force freeing all filesystems that are not in use */
232 static int locked
= 0;
234 struct vfs_stamping
*stamp
, *st
;
236 /* Avoid recursive invocation, e.g. when one of the free functions
242 gettimeofday (&time
, NULL
);
243 time
.tv_sec
-= vfs_timeout
;
245 for (stamp
= stamps
; stamp
!= NULL
;) {
246 if (now
|| (timeoutcmp (&stamp
->time
, &time
))) {
249 (*stamp
->v
->free
) (stamp
->id
);
250 vfs_rmstamp (stamp
->v
, stamp
->id
);
260 * Return the number of seconds remaining to the vfs timeout.
261 * FIXME: The code should be improved to actually return the number of
262 * seconds until the next item times out.
267 return stamps
? 10 : 0;
272 vfs_timeout_handler (void)
279 vfs_release_path (const char *dir
)
281 struct vfs_class
*oldvfs
;
284 oldvfs
= vfs_get_class (dir
);
285 oldvfsid
= vfs_getid (oldvfs
, dir
);
286 vfs_stamp_create (oldvfs
, oldvfsid
);
294 struct vfs_stamping
*stamp
, *st
;
296 for (stamp
= stamps
, stamps
= 0; stamp
!= NULL
;) {
298 (*stamp
->v
->free
) (stamp
->id
);
305 vfs_rmstamp (stamps
->v
, stamps
->id
);