* vfs.c: Allocate handles dynamically.

(get_bucket): Rewrite as vfs_new_handle().
(vfs_op): Make a function.
(vfs_info): Likewise.
(vfs_free_bucket): Replace with vfs_free_handle().
(mc_readdir): Expand, eliminate MC_DIROP.
This commit is contained in:
Pavel Roskin 2003-11-05 00:12:25 +00:00
parent 29486f10ef
commit c468c1b6e9
2 changed files with 104 additions and 50 deletions

View File

@ -1,3 +1,12 @@
2003-11-04 Pavel Roskin <proski@gnu.org>
* vfs.c: Allocate handles dynamically.
(get_bucket): Rewrite as vfs_new_handle().
(vfs_op): Make a function.
(vfs_info): Likewise.
(vfs_free_bucket): Replace with vfs_free_handle().
(mc_readdir): Expand, eliminate MC_DIROP.
2003-10-30 Pavel Roskin <proski@gnu.org>
* HACKING: New file - technical documentation for VFS.

145
vfs/vfs.c
View File

@ -65,29 +65,84 @@ static int current_mday;
static int current_mon;
static int current_year;
/* FIXME: Open files managed by the vfs layer, should be dynamical */
#define MAX_VFS_FILES 100
struct vfs_openfile {
int handle;
struct vfs_class *vclass;
void *fsinfo;
};
static struct {
void *fs_info;
struct vfs_class *operations;
} vfs_file_table [MAX_VFS_FILES];
static GSList *vfs_openfiles;
#define VFS_FIRST_HANDLE 100
static struct vfs_class *localfs_class;
/* Create new VFS handle and put it to the list */
static int
get_bucket (void)
vfs_new_handle (struct vfs_class *vclass, void *fsinfo)
{
int i;
static int vfs_handle_counter = VFS_FIRST_HANDLE;
struct vfs_openfile *h;
/* 0, 1, 2 are reserved file descriptors, while (DIR *) 0 means error */
for (i = 3; i < MAX_VFS_FILES; i++){
if (!vfs_file_table [i].fs_info)
return i;
}
h = g_new (struct vfs_openfile, 1);
h->handle = vfs_handle_counter++;
h->fsinfo = fsinfo;
h->vclass = vclass;
vfs_openfiles = g_slist_prepend (vfs_openfiles, h);
return h->handle;
}
vfs_die ("No more virtual file handles");
return 0;
/* Function to match handle, passed to g_slist_find_custom() */
static gint
vfs_cmp_handle (gconstpointer a, gconstpointer b)
{
if (!a)
return 1;
return ((struct vfs_openfile *) a)->handle != (int) b;
}
/* Find VFS class by file handle */
static inline struct vfs_class *
vfs_op (int handle)
{
GSList *l;
struct vfs_openfile *h;
l = g_slist_find_custom (vfs_openfiles, (gconstpointer) handle,
vfs_cmp_handle);
if (!l)
return NULL;
h = (struct vfs_openfile *) l->data;
if (!h)
return NULL;
return h->vclass;
}
/* Find private file data by file handle */
static inline void *
vfs_info (int handle)
{
GSList *l;
struct vfs_openfile *h;
l = g_slist_find_custom (vfs_openfiles, (gconstpointer) handle,
vfs_cmp_handle);
if (!l)
return NULL;
h = (struct vfs_openfile *) l->data;
if (!h)
return NULL;
return h->fsinfo;
}
/* Free open file data for given file handle */
static inline void
vfs_free_handle (int handle)
{
GSList *l;
l = g_slist_find_custom (vfs_openfiles, (gconstpointer) handle,
vfs_cmp_handle);
vfs_openfiles = g_slist_delete_link (vfs_openfiles, l);
}
static struct vfs_class *vfs_list;
@ -378,7 +433,6 @@ ferrno (struct vfs_class *vfs)
int
mc_open (const char *filename, int flags, ...)
{
int handle;
int mode;
void *info;
va_list ap;
@ -403,16 +457,9 @@ mc_open (const char *filename, int flags, ...)
errno = ferrno (vfs);
return -1;
}
handle = get_bucket ();
vfs_file_table [handle].fs_info = info;
vfs_file_table [handle].operations = vfs;
return handle;
}
#define vfs_op(handle) vfs_file_table [handle].operations
#define vfs_info(handle) vfs_file_table [handle].fs_info
#define vfs_free_bucket(handle) vfs_info(handle) = 0;
return vfs_new_handle (vfs, info);
}
#define MC_OP(name, inarg, callarg, pre, post) \
int mc_##name inarg \
@ -475,7 +522,7 @@ mc_close (int handle)
if (!vfs->close)
vfs_die ("VFS must support close.\n");
result = (*vfs->close)(vfs_info (handle));
vfs_free_bucket (handle);
vfs_free_handle (handle);
if (result == -1)
errno = ferrno (vfs);
@ -498,35 +545,32 @@ mc_opendir (char *dirname)
errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP;
return NULL;
}
handle = get_bucket ();
vfs_file_table [handle].fs_info = info;
vfs_file_table [handle].operations = vfs;
handle = vfs_new_handle (vfs, info);
handlep = g_new (int, 1);
*handlep = handle;
return (DIR *) handlep;
}
#define MC_DIROP(name, type, onerr ) \
type mc_##name (DIR *dirp) \
{ \
int handle; \
struct vfs_class *vfs; \
type result; \
\
if (!dirp){ \
errno = EFAULT; \
return onerr; \
} \
handle = *(int *) dirp; \
vfs = vfs_op (handle); \
result = vfs->name ? (*vfs->name) (vfs_info (handle)) : onerr; \
if (result == onerr) \
errno = vfs->name ? ferrno(vfs) : E_NOTSUPP; \
return result; \
}
struct dirent *
mc_readdir (DIR *dirp)
{
int handle;
struct vfs_class *vfs;
struct dirent *result = NULL;
MC_DIROP (readdir, struct dirent *, NULL)
if (!dirp) {
errno = EFAULT;
return NULL;
}
handle = *(int *) dirp;
vfs = vfs_op (handle);
if (vfs->readdir)
result = (*vfs->readdir) (vfs_info (handle));
if (!result)
errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
return result;
}
int
mc_closedir (DIR *dirp)
@ -536,7 +580,7 @@ mc_closedir (DIR *dirp)
int result;
result = vfs->closedir ? (*vfs->closedir)(vfs_info (handle)) : -1;
vfs_free_bucket (handle);
vfs_free_handle (handle);
g_free (dirp);
return result;
}
@ -1182,7 +1226,6 @@ vfs_init (void)
time_t current_time;
struct tm *t;
memset (vfs_file_table, 0, sizeof (vfs_file_table));
current_time = time (NULL);
t = localtime (&current_time);
current_mday = t->tm_mday;
@ -1240,6 +1283,8 @@ vfs_shut (void)
for (vfs=vfs_list; vfs; vfs=vfs->next)
if (vfs->done)
(*vfs->done) (vfs);
g_slist_free (vfs_openfiles);
}
/*