/trunk/uspace/app/tester/vfs/vfs1.c |
---|
30,11 → 30,12 |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <sys/types.h> |
#include <vfs.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include "../tester.h" |
char *test_vfs1(bool quiet) |
42,6 → 43,8 |
if (mount("tmpfs", "/", "nulldev0") != EOK) |
return "Mount failed.\n"; |
if (mkdir("/mydir", 0) != 0) |
return "mkdir() failed.\n"; |
DIR *dirp; |
struct dirent *dp; |
/trunk/uspace/lib/libc/include/sys/stat.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_SYS_STAT_H_ |
#define LIBC_SYS_STAT_H_ |
#include <sys/types.h> |
extern int mkdir(const char *, mode_t); |
#endif |
/** @} |
*/ |
/trunk/uspace/lib/libc/include/sys/types.h |
---|
40,6 → 40,7 |
typedef unsigned long size_t; |
typedef signed long ssize_t; |
typedef long off_t; |
typedef int mode_t; |
#endif |
/trunk/uspace/lib/libc/generic/vfs.c |
---|
37,6 → 37,8 |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <async.h> |
131,6 → 133,11 |
return _open(path, L_FILE, oflag); |
} |
int close(int fildes) |
{ |
return 0; /* TODO */ |
} |
ssize_t read(int fildes, void *buf, size_t nbyte) |
{ |
int res; |
209,7 → 216,7 |
off_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
&newoffs); |
(ipcarg_t)&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
274,9 → 281,35 |
return 0; |
} |
int close(int fildes) |
int mkdir(const char *path, mode_t mode) |
{ |
return 0; /* TODO */ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, &answer); |
rc = ipc_data_write_start(vfs_phone, path, strlen(path)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return EOK; |
} |
/** @} |
/trunk/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
211,7 → 211,42 |
static unsigned long create_node(tmpfs_dentry_t *dentry, |
const char *component, int lflag) |
{ |
return 0; |
assert(dentry->type == TMPFS_DIRECTORY); |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t)); |
if (!node) |
return 0; |
size_t len = strlen(component); |
char *name = malloc(len + 1); |
if (!name) { |
free(node); |
return 0; |
} |
strcpy(name, component); |
tmpfs_dentry_initialize(node); |
node->index = tmpfs_next_index++; |
node->name = name; |
node->parent = dentry; |
if (lflag & L_DIRECTORY) |
node->type = TMPFS_DIRECTORY; |
else |
node->type = TMPFS_FILE; |
/* Insert the new node into the namespace. */ |
if (dentry->child) { |
tmpfs_dentry_t *tmp = dentry->child; |
while (tmp->sibling) |
tmp = tmp->sibling; |
tmp->sibling = node; |
} else { |
dentry->child = node; |
} |
/* Insert the new node into the dentry hash table. */ |
hash_table_insert(&dentries, &node->index, &node->dh_link); |
return node->index; |
} |
static int destroy_component(tmpfs_dentry_t *dentry) |
256,7 → 291,7 |
} |
component[len++] = PLB_GET_CHAR(next); |
next++; /* process next character */ |
if (next <= last) |
if (next <= last) |
continue; |
} |
279,7 → 314,7 |
} |
unsigned long index = create_node(dcur, |
component, lflag); |
if (index) { |
if (index > 0) { |
ipc_answer_4(rid, EOK, |
tmpfs_reg.fs_handle, dev_handle, |
index, 0); |
/trunk/uspace/srv/vfs/vfs.c |
---|
105,13 → 105,9 |
case VFS_TRUNCATE: |
vfs_truncate(callid, &call); |
break; |
case VFS_UNMOUNT: |
case VFS_CLOSE: |
case VFS_UNLINK: |
case VFS_RENAME: |
case VFS_OPENDIR: |
case VFS_READDIR: |
case VFS_CLOSEDIR: |
case VFS_MKDIR: |
vfs_mkdir(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
/trunk/uspace/srv/vfs/vfs_ops.c |
---|
115,9 → 115,7 |
return; |
} |
/* |
* Deliver the file system name. |
*/ |
/* Deliver the file system name. */ |
char fs_name[FS_NAME_MAXLEN + 1]; |
(void) ipc_data_write_finalize(callid, fs_name, size); |
fs_name[size] = '\0'; |
132,9 → 130,7 |
return; |
} |
/* |
* Now, we want the client to send us the mount point. |
*/ |
/* Now, we want the client to send us the mount point. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
141,17 → 137,13 |
return; |
} |
/* |
* Check whether size is reasonable wrt. the mount point. |
*/ |
/* Check whether size is reasonable wrt. the mount point. */ |
if (size < 1 || size > MAX_PATH_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Allocate buffer for the mount point data being received. |
*/ |
/* Allocate buffer for the mount point data being received. */ |
uint8_t *buf; |
buf = malloc(size); |
if (!buf) { |
160,9 → 152,7 |
return; |
} |
/* |
* Deliver the mount point. |
*/ |
/* Deliver the mount point. */ |
(void) ipc_data_write_finalize(callid, buf, size); |
/* |
186,22 → 176,16 |
return; |
} |
/* |
* Finally, we need to resolve the path to the mountpoint. |
*/ |
/* Finally, we need to resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
futex_down(&rootfs_futex); |
if (rootfs.fs_handle) { |
/* |
* We already have the root FS. |
*/ |
/* We already have the root FS. */ |
rwlock_write_lock(&namespace_rwlock); |
rc = vfs_lookup_internal(buf, size, L_DIRECTORY, &mp_res, |
NULL); |
if (rc != EOK) { |
/* |
* The lookup failed for some reason. |
*/ |
/* The lookup failed for some reason. */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
225,13 → 209,9 |
*/ |
rwlock_write_unlock(&namespace_rwlock); |
} else { |
/* |
* We still don't have the root file system mounted. |
*/ |
/* We still don't have the root file system mounted. */ |
if ((size == 1) && (buf[0] == '/')) { |
/* |
* For this simple, but important case, we are done. |
*/ |
/* For this simple, but important case, we are done. */ |
rootfs = mr_res.triplet; |
futex_up(&rootfs_futex); |
free(buf); |
347,9 → 327,7 |
*/ |
rwlock_read_lock(&namespace_rwlock); |
/* |
* The path is now populated and we can call vfs_lookup_internal(). |
*/ |
/* The path is now populated and we can call vfs_lookup_internal(). */ |
vfs_lookup_res_t lr; |
rc = vfs_lookup_internal(path, len, lflag, &lr, NULL); |
if (rc) { |
359,9 → 337,7 |
return; |
} |
/* |
* Path is no longer needed. |
*/ |
/** Path is no longer needed. */ |
free(path); |
vfs_node_t *node = vfs_node_get(&lr); |
390,9 → 366,7 |
vfs_node_addref(node); |
vfs_node_put(node); |
/* |
* Success! Return the new file descriptor to the client. |
*/ |
/* Success! Return the new file descriptor to the client. */ |
ipc_answer_1(rid, EOK, fd); |
} |
411,9 → 385,7 |
int fd = IPC_GET_ARG1(*request); |
/* |
* Lookup the file structure corresponding to the file descriptor. |
*/ |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
453,9 → 425,7 |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* |
* Make a VFS_READ/VFS_WRITE request at the destination FS server. |
*/ |
/* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request), |
471,16 → 441,12 |
vfs_release_phone(fs_phone); |
/* |
* Wait for reply from the FS server. |
*/ |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
/* |
* Unlock the VFS node. |
*/ |
/* Unlock the VFS node. */ |
if (read) |
rwlock_read_unlock(&file->node->contents_rwlock); |
else { |
489,9 → 455,7 |
rwlock_write_unlock(&file->node->contents_rwlock); |
} |
/* |
* Update the position pointer and unlock the open file. |
*/ |
/* Update the position pointer and unlock the open file. */ |
file->pos += bytes; |
futex_up(&file->lock); |
519,9 → 483,7 |
int whence = (int) IPC_GET_ARG3(*request); |
/* |
* Lookup the file structure corresponding to the file descriptor. |
*/ |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
ipc_answer_0(rid, ENOENT); |
581,8 → 543,9 |
rwlock_write_lock(&file->node->contents_rwlock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)file->node->dev_handle, |
(ipcarg_t)file->node->index, (ipcarg_t)size); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, |
(ipcarg_t)file->node->dev_handle, (ipcarg_t)file->node->index, |
(ipcarg_t)size); |
vfs_release_phone(fs_phone); |
if (rc == EOK) |
file->node->size = size; |
592,6 → 555,48 |
ipc_answer_0(rid, rc); |
} |
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request) |
{ |
int mode = IPC_GET_ARG1(*request); |
size_t len; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Now we are on the verge of accepting the path. |
* |
* There is one optimization we could do in the future: copy the path |
* directly into the PLB using some kind of a callback. |
*/ |
char *path = malloc(len); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
free(path); |
return; |
} |
rwlock_write_lock(&namespace_rwlock); |
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE; |
rc = vfs_lookup_internal(path, len, lflag, NULL, NULL); |
rwlock_write_unlock(&namespace_rwlock); |
free(path); |
ipc_answer_0(rid, rc); |
} |
/** |
* @} |
*/ |
/trunk/uspace/srv/vfs/vfs.h |
---|
56,6 → 56,7 |
VFS_OPENDIR, |
VFS_READDIR, |
VFS_CLOSEDIR, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_MOUNT, |
VFS_UNMOUNT, |
261,6 → 262,7 |
extern void vfs_write(ipc_callid_t, ipc_call_t *); |
extern void vfs_seek(ipc_callid_t, ipc_call_t *); |
extern void vfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *); |
#endif |
/trunk/uspace/srv/vfs/vfs_lookup.c |
---|
57,6 → 57,7 |
* @param len Number of path characters pointed by path. |
* @param lflag Flags to be used during lookup. |
* @param result Empty structure where the lookup result will be stored. |
* Can be NULL. |
* @param altroot If non-empty, will be used instead of rootfs as the root |
* of the whole VFS tree. |
* |
162,7 → 163,7 |
memset(plb, 0, cnt2); |
futex_up(&plb_futex); |
if (rc == EOK) { |
if ((rc == EOK) && result) { |
result->triplet.fs_handle = (int) IPC_GET_ARG1(answer); |
result->triplet.dev_handle = (int) IPC_GET_ARG2(answer); |
result->triplet.index = (int) IPC_GET_ARG3(answer); |