minix/minix/lib/libfsdriver/utility.c
David van Moolenbroek 89c9de7d09 Add libfsdriver: a library to drive file systems
This library provides new abstractions for the upper (VFS) side of
file system services, and should be used for all file system service
implementations from now on.  It provides the following functionality:

  - a function call table abstraction, hiding the details of the
    VFS-FS protocol with simple parameters;
  - a (currently limited) number of per-function steps required for
    all file system implementations, such as copying in and out path
    names and result buffers;
  - a default implementation for multicomponent path lookups, such
    that the file system merely has to implement resolution of single
    components at a time;
  - an abstraction for copying data from and to the file system, which
    allows transparent intraprocess copying as required for the lookup
    implementation;
  - a set of functions to simplify getdents implementations.

The message loop provided by the library is currently for use by
single-threaded file system implementations only.  Multithreaded file
system services may use the more low-level message processing
functionality.

Protocol-level optimizations such as including names in protocol
messages may be hidden entirely in this library.  In addition, in the
future, the lookup implementation may be replaced by a single-
component lookup VFS/FS protocol request as part of a VFS name cache
implementation; this, too, can be hidden entirely in this library.

Change-Id: Ib34f0d0e021dfa3426ce8826efcf3eaa94d3ef3e
2014-09-18 12:46:23 +00:00

106 lines
2.1 KiB
C

#include "fsdriver.h"
/*
* Copy data from the caller into the local address space.
*/
int
fsdriver_copyin(const struct fsdriver_data * data, size_t off, void * ptr,
size_t len)
{
/* Do nothing for peek requests. */
if (data == NULL)
return OK;
/* The data size field is used only for this integrity check. */
if (off + len > data->size)
panic("fsdriver: copy-in buffer overflow");
if (data->endpt == SELF) {
memcpy(ptr, &data->ptr[off], len);
return OK;
}
return sys_safecopyfrom(data->endpt, data->grant, off, (vir_bytes)ptr,
(phys_bytes)len);
}
/*
* Copy data from the local address space to the caller.
*/
int
fsdriver_copyout(const struct fsdriver_data * data, size_t off,
const void * ptr, size_t len)
{
/* Do nothing for peek requests. */
if (data == NULL)
return OK;
/* The data size field is used only for this integrity check. */
if (off + len > data->size)
panic("fsdriver: copy-out buffer overflow");
if (data->endpt == SELF) {
memcpy(&data->ptr[off], ptr, len);
return OK;
}
return sys_safecopyto(data->endpt, data->grant, off, (vir_bytes)ptr,
(phys_bytes)len);
}
/*
* Zero out a data region in the caller.
*/
int
fsdriver_zero(const struct fsdriver_data * data, size_t off, size_t len)
{
/* Do nothing for peek requests. */
if (data == NULL)
return OK;
/* The data size field is used only for this integrity check. */
if (off + len > data->size)
panic("fsdriver: copy-out buffer overflow");
if (data->endpt == SELF) {
memset(&data->ptr[off], 0, len);
return OK;
}
return sys_safememset(data->endpt, data->grant, off, 0, len);
}
/*
* Copy in a null-terminated name, and perform sanity checks.
*/
int
fsdriver_getname(endpoint_t endpt, cp_grant_id_t grant, size_t len,
char * name, size_t size, int not_empty)
{
int r;
/* The given length includes the null terminator. */
if (len == 0 || (not_empty && len == 1))
return EINVAL;
if (len > size)
return ENAMETOOLONG;
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)name,
(phys_bytes)len)) != OK)
return r;
if (name[len - 1] != 0) {
printf("fsdriver: name not null-terminated\n");
return EINVAL;
}
return OK;
}