2 * Single File fileSystem
4 * Copyright 1998 Pavel Machek, distribute under GPL
6 * This defines whole class of filesystems which contain single file
7 * inside. It is somehow similar to extfs, except that extfs makes
8 * whole virtual trees and we do only single virtual files.
10 * If you want to gunzip something, you should open it with #ugz
11 * suffix, DON'T try to gunzip it yourself.
13 * Namespace: exports vfs_sfs_ops, shell (FIXME) */
17 #include <sys/types.h>
28 /* This is needed, or libvfs.so will lack symbol shell. Should look up who requires it */
29 char *shell
= "/bin/sh";
34 struct cachedfile
*next
;
37 static struct cachedfile
*head
;
40 static int sfs_no
= 0;
41 static char *sfs_prefix
[ MAXFS
];
42 static char *sfs_command
[ MAXFS
];
43 static int sfs_flags
[ MAXFS
];
46 #define F_NOLOCALCOPY 4
49 static int uptodate (char *name
, char *cache
)
54 static int vfmake (vfs
*me
, char *name
, char *cache
)
62 vfs_split (name
, &inpath
, &op
);
63 if ((w
= (*me
->which
) (me
, op
)) == -1)
64 vfs_die ("This cannot happen... Hopefully.\n");
66 if ((sfs_flags
[w
] & F_1
) || (!strcmp (name
, "/"))) ; else return -1;
67 /* if ((sfs_flags[w] & F_2) || (!inpath) || (!*inpath)); else return -1; */
68 if (!(sfs_flags
[w
] & F_NOLOCALCOPY
))
69 name
= mc_getlocalcopy (name
);
71 name
= g_strdup (name
);
73 #define COPY_CHAR if (t-pad>10200) return -1; else *t++ = *s;
74 #define COPY_STRING(a) if ((t-pad)+strlen(a)>10200) return -1; else { strcpy (t, a); t+= strlen(a); }
78 case '1': COPY_STRING (name
); break;
79 case '2': COPY_STRING (op
+ strlen (sfs_prefix
[w
])); break;
80 case '3': COPY_STRING (cache
); break;
81 case '%': COPY_CHAR
; break;
94 if (my_system (EXECUTE_AS_SHELL
| EXECUTE_SETUID
| EXECUTE_WAIT
, "/bin/sh", pad
)) {
102 redirect (vfs
*me
, char *name
)
104 struct cachedfile
*cur
= head
;
110 if ((!strcmp (name
, cur
->name
)) &&
112 (uptodate (cur
->name
, cur
->cache
)))
113 /* FIXME: when not uptodate, we might want to kill cache
114 * file immediately, not to wait until timeout. */ {
115 vfs_stamp (&vfs_sfs_ops
, cur
);
121 cache
= tempnam (NULL
, "sfs");
122 handle
= open (cache
, O_RDWR
| O_CREAT
| O_EXCL
, 0600);
124 return "/SOMEONE_PLAYING_DIRTY_TMP_TRICKS_ON_US";
128 xname
= g_strdup (name
);
129 if (!vfmake (me
, name
, cache
)){
130 cur
= g_new (struct cachedfile
, 1);
137 vfs_add_noncurrent_stamps (&vfs_sfs_ops
, (vfsid
) head
, NULL
);
138 vfs_rm_parents (NULL
);
144 return "/I_MUST_NOT_EXIST";
148 sfs_open (vfs
*me
, char *path
, int flags
, int mode
)
153 path
= redirect (me
, path
);
154 fd
= open (path
, flags
, mode
);
158 sfs_info
= g_new (int, 1);
164 static int sfs_stat (vfs
*me
, char *path
, struct stat
*buf
)
166 path
= redirect (me
, path
);
167 return stat (path
, buf
);
170 static int sfs_lstat (vfs
*me
, char *path
, struct stat
*buf
)
172 path
= redirect (me
, path
);
173 #ifndef HAVE_STATLSTAT
174 return lstat (path
,buf
);
176 return statlstat (path
, buf
);
180 static int sfs_chmod (vfs
*me
, char *path
, int mode
)
182 path
= redirect (me
, path
);
183 return chmod (path
, mode
);
186 static int sfs_chown (vfs
*me
, char *path
, int owner
, int group
)
188 path
= redirect (me
, path
);
189 return chown (path
, owner
, group
);
192 static int sfs_utime (vfs
*me
, char *path
, struct utimbuf
*times
)
194 path
= redirect (me
, path
);
195 return utime (path
, times
);
198 static int sfs_readlink (vfs
*me
, char *path
, char *buf
, int size
)
200 path
= redirect (me
, path
);
201 return readlink (path
, buf
, size
);
204 static vfsid
sfs_getid (vfs
*me
, char *path
, struct vfs_stamping
**parent
)
205 { /* FIXME: what should I do? */
208 struct vfs_stamping
*par
;
209 struct cachedfile
*cur
= head
;
212 if ((!strcmp( path
, cur
->name
)) &&
213 (vfs_uid
== cur
->uid
))
218 vfs_die( "sfs_getid of noncached thingie?" );
223 char *path2
= g_strdup (path
);
224 v
= vfs_split (path2
, NULL
, NULL
);
225 id
= (*v
->getid
) (v
, path2
, &par
);
229 if (id
!= (vfsid
)-1) {
230 *parent
= g_new (struct vfs_stamping
, 1);
233 (*parent
)->parent
= par
;
234 (*parent
)->next
= NULL
;
239 static void sfs_free (vfsid id
)
241 struct cachedfile
*which
= (struct cachedfile
*) id
;
242 struct cachedfile
*cur
, *prev
;
244 for (cur
= head
, prev
= 0; cur
&& cur
!= which
; prev
= cur
, cur
= cur
->next
)
247 vfs_die( "Free of thing which is unknown to me\n" );
251 prev
->next
= cur
->next
;
256 static void sfs_fill_names (vfs
*me
, void (*func
)(char *))
258 struct cachedfile
*cur
= head
;
266 static int sfs_nothingisopen (vfsid id
)
268 /* FIXME: Investigate whether have to guard this like in
269 the other VFSs (see fd_usage in extfs) -- Norbert */
273 static char *sfs_getlocalcopy (vfs
*me
, char *path
)
275 path
= redirect (me
, path
);
276 return g_strdup (path
);
279 static void sfs_ungetlocalcopy (vfs
*me
, char *path
, char *local
, int has_changed
)
283 static int sfs_init (vfs
*me
)
285 FILE *cfg
= fopen (LIBDIR
"extfs/sfs.ini", "r");
288 fprintf (stderr
, "Warning: " LIBDIR
"extfs/sfs.ini not found\n");
293 while (sfs_no
< MAXFS
){
295 char *c
, *semi
= NULL
, flags
= 0;
298 if (!fgets (key
, 250, cfg
))
304 for (i
= 0; i
< strlen (key
); i
++)
305 if ((key
[i
]==':') || (key
[i
]=='/')){
309 flags
|= F_FULLMATCH
;
315 fprintf (stderr
, "Warning: Invalid line %s in sfs.ini.\n", key
);
320 while ((*c
!= ' ') && (*c
!= 9)) {
322 case '1': flags
|= F_1
; break;
323 case '2': flags
|= F_2
; break;
324 case 'R': flags
|= F_NOLOCALCOPY
; break;
326 fprintf (stderr
, "Warning: Invalid flag %c in sfs.ini line %s.\n", *c
, key
);
332 if ((semi
= strchr (c
, '\n')))
335 sfs_prefix
[sfs_no
] = g_strdup (key
);
336 sfs_command
[sfs_no
] = g_strdup (c
);
337 sfs_flags
[sfs_no
] = flags
;
349 for (i
= 0; i
< sfs_no
; i
++){
350 g_free (sfs_prefix
[i
]);
351 g_free (sfs_command
[i
]);
352 sfs_prefix
[i
] = sfs_command
[i
] = NULL
;
358 sfs_which (vfs
*me
, char *path
)
362 for (i
= 0; i
< sfs_no
; i
++)
363 if (sfs_flags
[i
] & F_FULLMATCH
) {
364 if (!strcmp (path
, sfs_prefix
[i
]))
367 if (!strncmp (path
, sfs_prefix
[i
], strlen (sfs_prefix
[i
])))
375 NULL
, /* This is place of next pointer */
376 "Signle file filesystems",