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 "vfs.h"
00039 #include <macros.h>
00040 #include <async.h>
00041 #include <errno.h>
00042 #include <str.h>
00043 #include <stdarg.h>
00044 #include <bool.h>
00045 #include <fibril_synch.h>
00046 #include <adt/list.h>
00047 #include <vfs/canonify.h>
00048
00049 #define min(a, b) ((a) < (b) ? (a) : (b))
00050
00051 FIBRIL_MUTEX_INITIALIZE(plb_mutex);
00052 LIST_INITIALIZE(plb_head);
00053 uint8_t *plb = NULL;
00054
00068 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
00069 vfs_pair_t *altroot, ...)
00070 {
00071 vfs_pair_t *root;
00072
00073 if (altroot)
00074 root = altroot;
00075 else
00076 root = &rootfs;
00077
00078 if (!root->fs_handle)
00079 return ENOENT;
00080
00081 size_t len;
00082 path = canonify(path, &len);
00083 if (!path)
00084 return EINVAL;
00085
00086 fs_index_t index = 0;
00087 if (lflag & L_LINK) {
00088 va_list ap;
00089
00090 va_start(ap, altroot);
00091 index = va_arg(ap, fs_index_t);
00092 va_end(ap);
00093 }
00094
00095 fibril_mutex_lock(&plb_mutex);
00096
00097 plb_entry_t entry;
00098 link_initialize(&entry.plb_link);
00099 entry.len = len;
00100
00101 size_t first;
00102 size_t last;
00103
00104 if (list_empty(&plb_head)) {
00105 first = 0;
00106 last = PLB_SIZE - 1;
00107 } else {
00108 plb_entry_t *oldest = list_get_instance(plb_head.next,
00109 plb_entry_t, plb_link);
00110 plb_entry_t *newest = list_get_instance(plb_head.prev,
00111 plb_entry_t, plb_link);
00112
00113 first = (newest->index + newest->len) % PLB_SIZE;
00114 last = (oldest->index - 1) % PLB_SIZE;
00115 }
00116
00117 if (first <= last) {
00118 if ((last - first) + 1 < len) {
00119
00120
00121
00122 fibril_mutex_unlock(&plb_mutex);
00123 return ELIMIT;
00124 }
00125 } else {
00126 if (PLB_SIZE - ((first - last) + 1) < len) {
00127
00128
00129
00130 fibril_mutex_unlock(&plb_mutex);
00131 return ELIMIT;
00132 }
00133 }
00134
00135
00136
00137
00138
00139
00140 entry.index = first;
00141 entry.len = len;
00142
00143
00144
00145
00146
00147 list_append(&entry.plb_link, &plb_head);
00148
00149 fibril_mutex_unlock(&plb_mutex);
00150
00151
00152
00153
00154 size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
00155 size_t cnt2 = len - cnt1;
00156
00157 memcpy(&plb[first], path, cnt1);
00158 memcpy(plb, &path[cnt1], cnt2);
00159
00160 ipc_call_t answer;
00161 int phone = vfs_grab_phone(root->fs_handle);
00162 aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (sysarg_t) first,
00163 (sysarg_t) (first + len - 1) % PLB_SIZE,
00164 (sysarg_t) root->devmap_handle, (sysarg_t) lflag, (sysarg_t) index,
00165 &answer);
00166
00167 sysarg_t rc;
00168 async_wait_for(req, &rc);
00169 vfs_release_phone(root->fs_handle, phone);
00170
00171 fibril_mutex_lock(&plb_mutex);
00172 list_remove(&entry.plb_link);
00173
00174
00175
00176 memset(&plb[first], 0, cnt1);
00177 memset(plb, 0, cnt2);
00178 fibril_mutex_unlock(&plb_mutex);
00179
00180 if ((int) rc < EOK)
00181 return (int) rc;
00182
00183 if (!result)
00184 return EOK;
00185
00186 result->triplet.fs_handle = (fs_handle_t) rc;
00187 result->triplet.devmap_handle = (devmap_handle_t) IPC_GET_ARG1(answer);
00188 result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
00189 result->size =
00190 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
00191 result->lnkcnt = (unsigned int) IPC_GET_ARG5(answer);
00192
00193 if (lflag & L_FILE)
00194 result->type = VFS_NODE_FILE;
00195 else if (lflag & L_DIRECTORY)
00196 result->type = VFS_NODE_DIRECTORY;
00197 else
00198 result->type = VFS_NODE_UNKNOWN;
00199
00200 return EOK;
00201 }
00202
00208 int vfs_open_node_internal(vfs_lookup_res_t *result)
00209 {
00210 int phone = vfs_grab_phone(result->triplet.fs_handle);
00211
00212 ipc_call_t answer;
00213 aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
00214 (sysarg_t) result->triplet.devmap_handle,
00215 (sysarg_t) result->triplet.index, &answer);
00216
00217 sysarg_t rc;
00218 async_wait_for(req, &rc);
00219 vfs_release_phone(result->triplet.fs_handle, phone);
00220
00221 if (rc == EOK) {
00222 result->size =
00223 MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
00224 result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
00225 if (IPC_GET_ARG4(answer) & L_FILE)
00226 result->type = VFS_NODE_FILE;
00227 else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
00228 result->type = VFS_NODE_DIRECTORY;
00229 else
00230 result->type = VFS_NODE_UNKNOWN;
00231 }
00232
00233 return rc;
00234 }
00235