Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2525 → Rev 2526

/trunk/uspace/lib/libc/include/libadt/hash_table.h
55,23 → 55,25
struct hash_table_operations {
/** Hash function.
*
* @param key Array of keys needed to compute hash index. All keys must be passed.
* @param key Array of keys needed to compute hash index. All keys
* must be passed.
*
* @return Index into hash table.
* @return Index into hash table.
*/
hash_index_t (* hash)(unsigned long key[]);
/** Hash table item comparison function.
*
* @param key Array of keys that will be compared with item. It is not necessary to pass all keys.
* @param key Array of keys that will be compared with item. It is
* not necessary to pass all keys.
*
* @return true if the keys match, false otherwise.
* @return true if the keys match, false otherwise.
*/
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
* @param item Item that was removed from the hash table.
* @param item Item that was removed from the hash table.
*/
void (*remove_callback)(link_t *item);
};
/trunk/uspace/lib/libc/include/ctype.h
35,9 → 35,19
#ifndef LIBC_CTYPE_H_
#define LIBC_CTYPE_H_
 
static inline int islower(int c)
{
return ((c >= 'a') && (c <= 'z'));
}
 
static inline int isupper(int c)
{
return ((c >= 'A') && (c <= 'Z'));
}
 
static inline int isalpha(int c)
{
return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
return (islower(c) || isupper(c));
}
 
static inline int isdigit(int c)
/trunk/uspace/srv/vfs/vfs.c
40,9 → 40,16
#include <async.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <futex.h>
#include <libadt/list.h>
#include "vfs.h"
 
atomic_t fs_head_futex = FUTEX_INITIALIZER;
link_t fs_head;
 
/** Verify the VFS info structure.
*
* @param info Info structure to be verified.
49,9 → 56,53
*
* @return Non-zero if the info structure is sane, zero otherwise.
*/
static int vfs_info_sane(vfs_info_t *info)
static bool vfs_info_sane(vfs_info_t *info)
{
return 1; /* XXX */
int i;
 
/*
* Check if the name is non-empty and is composed solely of ASCII
* characters [a-z]+[a-z0-9_-]*.
*/
if (!islower(info->name[0]))
return false;
for (i = 1; i < FS_NAME_MAXLEN; i++) {
if (!(islower(info->name[i]) || isdigit(info->name[i])) &&
(info->name[i] != '-') && (info->name[i] != '_')) {
if (info->name[i] == '\0')
break;
else
return false;
}
}
 
/*
* Check if the FS implements mandatory VFS operations.
*/
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_REGISTER)] != VFS_OP_DEFINED)
return false;
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] != VFS_OP_DEFINED)
return false;
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] != VFS_OP_DEFINED)
return false;
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_OPEN)] != VFS_OP_DEFINED)
return false;
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_CLOSE)] != VFS_OP_DEFINED)
return false;
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_READ)] != VFS_OP_DEFINED)
return false;
/*
* Check if each operation is either not defined, defined or default.
*/
for (i = VFS_FIRST; i < VFS_LAST; i++) {
if ((IPC_METHOD_TO_VFS_OP(i) != VFS_OP_NULL) &&
(IPC_METHOD_TO_VFS_OP(i) != VFS_OP_DEFAULT) &&
(IPC_METHOD_TO_VFS_OP(i) != VFS_OP_DEFINED))
return false;
}
return true;
}
 
/** VFS_REGISTER protocol function.
80,8 → 131,8
}
/*
* We know the size of the info structure. See if the client understands
* this easy concept too.
* We know the size of the VFS info structure. See if the client
* understands this easy concept too.
*/
if (size != sizeof(vfs_info_t)) {
/*
92,33 → 143,64
ipc_answer_fast(rid, EINVAL, 0, 0);
return;
}
vfs_info_t *info;
fs_info_t *fs_info;
 
/*
* Allocate a buffer for the info structure.
* Allocate and initialize a buffer for the fs_info structure.
*/
info = (vfs_info_t *) malloc(sizeof(vfs_info_t));
if (!info) {
fs_info = (fs_info_t *) malloc(sizeof(fs_info_t));
if (!fs_info) {
ipc_answer_fast(callid, ENOMEM, 0, 0);
ipc_answer_fast(rid, ENOMEM, 0, 0);
return;
}
link_initialize(&fs_info->fs_link);
rc = ipc_data_send_answer(callid, &call, info, size);
rc = ipc_data_send_answer(callid, &call, &fs_info->vfs_info, size);
if (!rc) {
free(info);
free(fs_info);
ipc_answer_fast(callid, rc, 0, 0);
ipc_answer_fast(rid, rc, 0, 0);
return;
}
if (!vfs_info_sane(info)) {
free(info);
if (!vfs_info_sane(&fs_info->vfs_info)) {
free(fs_info);
ipc_answer_fast(callid, EINVAL, 0, 0);
ipc_answer_fast(rid, EINVAL, 0, 0);
return;
}
futex_down(&fs_head_futex);
 
/*
* Check for duplicit registrations.
*/
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fi = list_get_instance(cur, fs_info_t,
fs_link);
/* TODO: replace strcmp with strncmp once we have it */
if (strcmp(fs_info->vfs_info.name, fi->vfs_info.name) == 0) {
/*
* We already register a fs like this.
*/
futex_up(&fs_head_futex);
free(fs_info);
ipc_answer_fast(callid, EEXISTS, 0, 0);
ipc_answer_fast(rid, EEXISTS, 0, 0);
return;
}
}
/*
* TODO:
* 1. send the client the IPC_M_CONNECT_TO_ME call so that it makes a
* callback connection.
* 2. add the fs_info into fs_head
*/
 
futex_up(&fs_head_futex);
}
 
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
177,6 → 259,7
{
ipcarg_t phonead;
 
list_initialize(&fs_head);
async_set_client_connection(vfs_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, &phonead);
async_manager();
/trunk/uspace/srv/vfs/vfs.h
37,6 → 37,8
 
#define VFS_FIRST FIRST_USER_METHOD
 
#define IPC_METHOD_TO_VFS_OP(m) ((m) - VFS_FIRST)
 
typedef enum {
VFS_REGISTER = VFS_FIRST,
VFS_MOUNT,
72,12 → 74,17
*/
typedef struct {
/** Unique identifier of the fs. */
char fs_name[FS_NAME_MAXLEN];
char name[FS_NAME_MAXLEN];
/** Operations. */
vfs_op_t ops[VFS_LAST - VFS_FIRST];
} vfs_info_t;
 
typedef struct {
link_t fs_link;
vfs_info_t vfs_info;
} fs_info_t;
 
#endif
 
/**