00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <errno.h>
00039 #include <stdlib.h>
00040 #include <str.h>
00041 #include <assert.h>
00042 #include <bool.h>
00043 #include <fibril.h>
00044 #include <fibril_synch.h>
00045 #include "vfs.h"
00046
00047 #define VFS_DATA ((vfs_client_data_t *) async_client_data_get())
00048 #define FILES (VFS_DATA->files)
00049
00050 typedef struct {
00051 fibril_mutex_t lock;
00052 vfs_file_t **files;
00053 } vfs_client_data_t;
00054
00056 static bool vfs_files_init(void)
00057 {
00058 fibril_mutex_lock(&VFS_DATA->lock);
00059 if (!FILES) {
00060 FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
00061 if (!FILES) {
00062 fibril_mutex_unlock(&VFS_DATA->lock);
00063 return false;
00064 }
00065 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
00066 }
00067 fibril_mutex_unlock(&VFS_DATA->lock);
00068 return true;
00069 }
00070
00072 static void vfs_files_done(void)
00073 {
00074 int i;
00075
00076 if (!FILES)
00077 return;
00078
00079 for (i = 0; i < MAX_OPEN_FILES; i++) {
00080 if (FILES[i]) {
00081 (void) vfs_fd_free(i);
00082 }
00083 }
00084
00085 free(FILES);
00086 }
00087
00088 void *vfs_client_data_create(void)
00089 {
00090 vfs_client_data_t *vfs_data;
00091
00092 vfs_data = malloc(sizeof(vfs_client_data_t));
00093 if (vfs_data) {
00094 fibril_mutex_initialize(&vfs_data->lock);
00095 vfs_data->files = NULL;
00096 }
00097
00098 return vfs_data;
00099 }
00100
00101 void vfs_client_data_destroy(void *data)
00102 {
00103 vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
00104
00105 vfs_files_done();
00106 free(vfs_data);
00107 }
00108
00110 static int vfs_file_close_remote(vfs_file_t *file)
00111 {
00112 ipc_call_t answer;
00113 aid_t msg;
00114 sysarg_t rc;
00115 int phone;
00116
00117 assert(!file->refcnt);
00118
00119 phone = vfs_grab_phone(file->node->fs_handle);
00120 msg = async_send_2(phone, VFS_OUT_CLOSE, file->node->devmap_handle,
00121 file->node->index, &answer);
00122 async_wait_for(msg, &rc);
00123 vfs_release_phone(file->node->fs_handle, phone);
00124
00125 return IPC_GET_ARG1(answer);
00126 }
00127
00128
00134 static void vfs_file_addref(vfs_file_t *file)
00135 {
00136 assert(fibril_mutex_is_locked(&VFS_DATA->lock));
00137
00138 file->refcnt++;
00139 }
00140
00146 static int vfs_file_delref(vfs_file_t *file)
00147 {
00148 int rc = EOK;
00149
00150 assert(fibril_mutex_is_locked(&VFS_DATA->lock));
00151
00152 if (file->refcnt-- == 1) {
00153
00154
00155
00156
00157 rc = vfs_file_close_remote(file);
00158 vfs_node_delref(file->node);
00159 free(file);
00160 }
00161
00162 return rc;
00163 }
00164
00165
00174 int vfs_fd_alloc(bool desc)
00175 {
00176 if (!vfs_files_init())
00177 return ENOMEM;
00178
00179 unsigned int i;
00180 if (desc)
00181 i = MAX_OPEN_FILES - 1;
00182 else
00183 i = 0;
00184
00185 fibril_mutex_lock(&VFS_DATA->lock);
00186 while (true) {
00187 if (!FILES[i]) {
00188 FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
00189 if (!FILES[i]) {
00190 fibril_mutex_unlock(&VFS_DATA->lock);
00191 return ENOMEM;
00192 }
00193
00194 memset(FILES[i], 0, sizeof(vfs_file_t));
00195 fibril_mutex_initialize(&FILES[i]->lock);
00196 vfs_file_addref(FILES[i]);
00197 fibril_mutex_unlock(&VFS_DATA->lock);
00198 return (int) i;
00199 }
00200
00201 if (desc) {
00202 if (i == 0)
00203 break;
00204
00205 i--;
00206 } else {
00207 if (i == MAX_OPEN_FILES - 1)
00208 break;
00209
00210 i++;
00211 }
00212 }
00213 fibril_mutex_unlock(&VFS_DATA->lock);
00214
00215 return EMFILE;
00216 }
00217
00225 int vfs_fd_free(int fd)
00226 {
00227 int rc;
00228
00229 if (!vfs_files_init())
00230 return ENOMEM;
00231
00232 fibril_mutex_lock(&VFS_DATA->lock);
00233 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
00234 fibril_mutex_unlock(&VFS_DATA->lock);
00235 return EBADF;
00236 }
00237
00238 rc = vfs_file_delref(FILES[fd]);
00239 FILES[fd] = NULL;
00240 fibril_mutex_unlock(&VFS_DATA->lock);
00241
00242 return rc;
00243 }
00244
00254 int vfs_fd_assign(vfs_file_t *file, int fd)
00255 {
00256 if (!vfs_files_init())
00257 return ENOMEM;
00258
00259 fibril_mutex_lock(&VFS_DATA->lock);
00260 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {
00261 fibril_mutex_unlock(&VFS_DATA->lock);
00262 return EINVAL;
00263 }
00264
00265 FILES[fd] = file;
00266 vfs_file_addref(FILES[fd]);
00267 fibril_mutex_unlock(&VFS_DATA->lock);
00268
00269 return EOK;
00270 }
00271
00278 vfs_file_t *vfs_file_get(int fd)
00279 {
00280 if (!vfs_files_init())
00281 return NULL;
00282
00283 fibril_mutex_lock(&VFS_DATA->lock);
00284 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
00285 vfs_file_t *file = FILES[fd];
00286 if (file != NULL) {
00287 vfs_file_addref(file);
00288 fibril_mutex_unlock(&VFS_DATA->lock);
00289 return file;
00290 }
00291 }
00292 fibril_mutex_unlock(&VFS_DATA->lock);
00293
00294 return NULL;
00295 }
00296
00301 void vfs_file_put(vfs_file_t *file)
00302 {
00303 fibril_mutex_lock(&VFS_DATA->lock);
00304 vfs_file_delref(file);
00305 fibril_mutex_unlock(&VFS_DATA->lock);
00306 }
00307