Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/devfs/devfs_ops.c

    rcfd630af r0143f72  
    3636 */
    3737
    38 #include <macros.h>
     38#include <ipc/ipc.h>
    3939#include <bool.h>
    4040#include <errno.h>
    4141#include <malloc.h>
    42 #include <str.h>
     42#include <string.h>
    4343#include <libfs.h>
    44 #include <fibril_synch.h>
     44#include <fibril_sync.h>
    4545#include <adt/hash_table.h>
    46 #include <ipc/devmap.h>
    4746#include <sys/stat.h>
    48 #include <libfs.h>
    49 #include <assert.h>
    5047#include "devfs.h"
    5148#include "devfs_ops.h"
    5249
    53 typedef struct {
    54         devmap_handle_type_t type;
    55         devmap_handle_t handle;
    56 } devfs_node_t;
     50#define PLB_GET_CHAR(pos)  (devfs_reg.plb_ro[pos % PLB_SIZE])
    5751
    5852/** Opened devices structure */
    5953typedef struct {
    60         devmap_handle_t handle;
    61         int phone;              /**< When < 0, the structure is incomplete. */
     54        dev_handle_t handle;
     55        int phone;
    6256        size_t refcount;
    6357        link_t link;
    64         fibril_condvar_t cv;    /**< Broadcast when completed. */
    6558} device_t;
    6659
     
    8477{
    8578        device_t *dev = hash_table_get_instance(item, device_t, link);
    86         return (dev->handle == (devmap_handle_t) key[DEVICES_KEY_HANDLE]);
     79        return (dev->handle == (dev_handle_t) key[DEVICES_KEY_HANDLE]);
    8780}
    8881
     
    9891};
    9992
    100 static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
    101     devmap_handle_t handle)
    102 {
    103         devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
    104         if (node == NULL) {
    105                 *rfn = NULL;
    106                 return ENOMEM;
    107         }
    108        
    109         *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
    110         if (*rfn == NULL) {
    111                 free(node);
    112                 *rfn = NULL;
    113                 return ENOMEM;
    114         }
    115        
    116         fs_node_initialize(*rfn);
    117         node->type = type;
    118         node->handle = handle;
    119        
    120         (*rfn)->data = node;
    121         return EOK;
    122 }
    123 
    124 static int devfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
    125 {
    126         return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
    127 }
    128 
    129 static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    130 {
    131         devfs_node_t *node = (devfs_node_t *) pfn->data;
    132         int ret;
    133        
    134         if (node->handle == 0) {
    135                 /* Root directory */
    136                
    137                 dev_desc_t *devs;
    138                 size_t count = devmap_get_namespaces(&devs);
    139                
    140                 if (count > 0) {
    141                         size_t pos;
    142                         for (pos = 0; pos < count; pos++) {
    143                                 /* Ignore root namespace */
    144                                 if (str_cmp(devs[pos].name, "") == 0)
    145                                         continue;
    146                                
    147                                 if (str_cmp(devs[pos].name, component) == 0) {
    148                                         ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
    149                                         free(devs);
    150                                         return ret;
    151                                 }
    152                         }
    153                        
    154                         free(devs);
    155                 }
    156                
    157                 /* Search root namespace */
    158                 devmap_handle_t namespace;
    159                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    160                         count = devmap_get_devices(namespace, &devs);
    161                        
    162                         if (count > 0) {
    163                                 size_t pos;
    164                                 for (pos = 0; pos < count; pos++) {
    165                                         if (str_cmp(devs[pos].name, component) == 0) {
    166                                                 ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    167                                                 free(devs);
    168                                                 return ret;
    169                                         }
    170                                 }
    171                                
    172                                 free(devs);
    173                         }
    174                 }
    175                
    176                 *rfn = NULL;
    177                 return EOK;
    178         }
    179        
    180         if (node->type == DEV_HANDLE_NAMESPACE) {
    181                 /* Namespace directory */
    182                
    183                 dev_desc_t *devs;
    184                 size_t count = devmap_get_devices(node->handle, &devs);
    185                 if (count > 0) {
    186                         size_t pos;
    187                         for (pos = 0; pos < count; pos++) {
    188                                 if (str_cmp(devs[pos].name, component) == 0) {
    189                                         ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    190                                         free(devs);
    191                                         return ret;
    192                                 }
    193                         }
    194                        
    195                         free(devs);
    196                 }
    197                
    198                 *rfn = NULL;
    199                 return EOK;
    200         }
    201        
    202         *rfn = NULL;
    203         return EOK;
    204 }
    205 
    206 static int devfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
    207 {
    208         return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
    209 }
    210 
    211 static int devfs_node_open(fs_node_t *fn)
    212 {
    213         devfs_node_t *node = (devfs_node_t *) fn->data;
    214        
    215         if (node->handle == 0) {
    216                 /* Root directory */
    217                 return EOK;
    218         }
    219        
    220         devmap_handle_type_t type = devmap_handle_probe(node->handle);
    221        
    222         if (type == DEV_HANDLE_NAMESPACE) {
    223                 /* Namespace directory */
    224                 return EOK;
    225         }
    226        
    227         if (type == DEV_HANDLE_DEVICE) {
    228                 /* Device node */
    229                
    230                 unsigned long key[] = {
    231                         [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
    232                 };
    233                 link_t *lnk;
    234 
    235                 fibril_mutex_lock(&devices_mutex);
    236 restart:
    237                 lnk = hash_table_find(&devices, key);
    238                 if (lnk == NULL) {
    239                         device_t *dev = (device_t *) malloc(sizeof(device_t));
    240                         if (dev == NULL) {
    241                                 fibril_mutex_unlock(&devices_mutex);
    242                                 return ENOMEM;
    243                         }
    244                        
    245                         dev->handle = node->handle;
    246                         dev->phone = -1;        /* mark as incomplete */
    247                         dev->refcount = 1;
    248                         fibril_condvar_initialize(&dev->cv);
    249 
    250                         /*
    251                          * Insert the incomplete device structure so that other
    252                          * fibrils will not race with us when we drop the mutex
    253                          * below.
    254                          */
    255                         hash_table_insert(&devices, key, &dev->link);
    256 
    257                         /*
    258                          * Drop the mutex to allow recursive devfs requests.
    259                          */
    260                         fibril_mutex_unlock(&devices_mutex);
    261 
    262                         int phone = devmap_device_connect(node->handle, 0);
    263 
    264                         fibril_mutex_lock(&devices_mutex);
    265 
    266                         /*
    267                          * Notify possible waiters about this device structure
    268                          * being completed (or destroyed).
    269                          */
    270                         fibril_condvar_broadcast(&dev->cv);
    271 
    272                         if (phone < 0) {
    273                                 /*
    274                                  * Connecting failed, need to remove the
    275                                  * entry and free the device structure.
    276                                  */
    277                                 hash_table_remove(&devices, key, DEVICES_KEYS);
    278                                 fibril_mutex_unlock(&devices_mutex);
    279 
    280                                 return ENOENT;
    281                         }
    282                        
    283                         /* Set the correct phone. */
    284                         dev->phone = phone;
    285                 } else {
    286                         device_t *dev = hash_table_get_instance(lnk, device_t, link);
    287 
    288                         if (dev->phone < 0) {
    289                                 /*
    290                                  * Wait until the device structure is completed
    291                                  * and start from the beginning as the device
    292                                  * structure might have entirely disappeared
    293                                  * while we were not holding the mutex in
    294                                  * fibril_condvar_wait().
    295                                  */
    296                                 fibril_condvar_wait(&dev->cv, &devices_mutex);
    297                                 goto restart;
    298                         }
    299 
    300                         dev->refcount++;
    301                 }
    302                
    303                 fibril_mutex_unlock(&devices_mutex);
    304                
    305                 return EOK;
    306         }
    307        
    308         return ENOENT;
    309 }
    310 
    311 static int devfs_node_put(fs_node_t *fn)
    312 {
    313         free(fn->data);
    314         free(fn);
    315         return EOK;
    316 }
    317 
    318 static int devfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
    319 {
    320         assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
    321        
    322         *rfn = NULL;
    323         return ENOTSUP;
    324 }
    325 
    326 static int devfs_destroy_node(fs_node_t *fn)
    327 {
    328         return ENOTSUP;
    329 }
    330 
    331 static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    332 {
    333         return ENOTSUP;
    334 }
    335 
    336 static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    337 {
    338         return ENOTSUP;
    339 }
    340 
    341 static int devfs_has_children(bool *has_children, fs_node_t *fn)
    342 {
    343         devfs_node_t *node = (devfs_node_t *) fn->data;
    344        
    345         if (node->handle == 0) {
    346                 size_t count = devmap_count_namespaces();
    347                 if (count > 0) {
    348                         *has_children = true;
    349                         return EOK;
    350                 }
    351                
    352                 /* Root namespace */
    353                 devmap_handle_t namespace;
    354                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    355                         count = devmap_count_devices(namespace);
    356                         if (count > 0) {
    357                                 *has_children = true;
    358                                 return EOK;
    359                         }
    360                 }
    361                
    362                 *has_children = false;
    363                 return EOK;
    364         }
    365        
    366         if (node->type == DEV_HANDLE_NAMESPACE) {
    367                 size_t count = devmap_count_devices(node->handle);
    368                 if (count > 0) {
    369                         *has_children = true;
    370                         return EOK;
    371                 }
    372                
    373                 *has_children = false;
    374                 return EOK;
    375         }
    376        
    377         *has_children = false;
    378         return EOK;
    379 }
    380 
    381 static fs_index_t devfs_index_get(fs_node_t *fn)
    382 {
    383         devfs_node_t *node = (devfs_node_t *) fn->data;
    384         return node->handle;
    385 }
    386 
    387 static aoff64_t devfs_size_get(fs_node_t *fn)
    388 {
    389         return 0;
    390 }
    391 
    392 static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
    393 {
    394         devfs_node_t *node = (devfs_node_t *) fn->data;
    395        
    396         if (node->handle == 0)
    397                 return 0;
    398        
    399         return 1;
    400 }
    401 
    402 static char devfs_plb_get_char(unsigned pos)
    403 {
    404         return devfs_reg.plb_ro[pos % PLB_SIZE];
    405 }
    406 
    407 static bool devfs_is_directory(fs_node_t *fn)
    408 {
    409         devfs_node_t *node = (devfs_node_t *) fn->data;
    410        
    411         return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
    412 }
    413 
    414 static bool devfs_is_file(fs_node_t *fn)
    415 {
    416         devfs_node_t *node = (devfs_node_t *) fn->data;
    417        
    418         return (node->type == DEV_HANDLE_DEVICE);
    419 }
    420 
    421 static devmap_handle_t devfs_device_get(fs_node_t *fn)
    422 {
    423         devfs_node_t *node = (devfs_node_t *) fn->data;
    424        
    425         if (node->type == DEV_HANDLE_DEVICE)
    426                 return node->handle;
    427        
    428         return 0;
    429 }
    430 
    431 /** libfs operations */
    432 libfs_ops_t devfs_libfs_ops = {
    433         .root_get = devfs_root_get,
    434         .match = devfs_match,
    435         .node_get = devfs_node_get,
    436         .node_open = devfs_node_open,
    437         .node_put = devfs_node_put,
    438         .create = devfs_create_node,
    439         .destroy = devfs_destroy_node,
    440         .link = devfs_link_node,
    441         .unlink = devfs_unlink_node,
    442         .has_children = devfs_has_children,
    443         .index_get = devfs_index_get,
    444         .size_get = devfs_size_get,
    445         .lnkcnt_get = devfs_lnkcnt_get,
    446         .plb_get_char = devfs_plb_get_char,
    447         .is_directory = devfs_is_directory,
    448         .is_file = devfs_is_file,
    449         .device_get = devfs_device_get
    450 };
    451 
    45293bool devfs_init(void)
    45394{
     
    45697                return false;
    45798       
     99        if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
     100                return false;
     101       
    458102        return true;
    459103}
     
    461105void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    462106{
    463         char *opts;
    464        
    465107        /* Accept the mount options */
    466         sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
    467             0, NULL);
     108        ipc_callid_t callid;
     109        size_t size;
     110        if (!ipc_data_write_receive(&callid, &size)) {
     111                ipc_answer_0(callid, EINVAL);
     112                ipc_answer_0(rid, EINVAL);
     113                return;
     114        }
     115       
     116        char *opts = malloc(size + 1);
     117        if (!opts) {
     118                ipc_answer_0(callid, ENOMEM);
     119                ipc_answer_0(rid, ENOMEM);
     120                return;
     121        }
     122       
     123        ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
    468124        if (retval != EOK) {
    469                 async_answer_0(rid, retval);
     125                ipc_answer_0(rid, retval);
     126                free(opts);
    470127                return;
    471128        }
    472129       
    473130        free(opts);
    474         async_answer_3(rid, EOK, 0, 0, 0);
     131       
     132        ipc_answer_3(rid, EOK, 0, 0, 0);
    475133}
    476134
    477135void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
    478136{
    479         libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    480 }
    481 
    482 void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
    483 {
    484         async_answer_0(rid, ENOTSUP);
    485 }
    486 
    487 void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
    488 {
    489         libfs_unmount(&devfs_libfs_ops, rid, request);
     137        ipc_answer_0(rid, ENOTSUP);
    490138}
    491139
    492140void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    493141{
    494         libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    495 }
    496 
    497 void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
    498 {
    499         libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    500 }
    501 
    502 void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
    503 {
    504         libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    505 }
    506 
    507 void devfs_read(ipc_callid_t rid, ipc_call_t *request)
    508 {
    509         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    510         aoff64_t pos =
    511             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    512        
    513         if (index == 0) {
    514                 ipc_callid_t callid;
    515                 size_t size;
    516                 if (!async_data_read_receive(&callid, &size)) {
    517                         async_answer_0(callid, EINVAL);
    518                         async_answer_0(rid, EINVAL);
    519                         return;
    520                 }
    521                
    522                 dev_desc_t *desc;
    523                 size_t count = devmap_get_namespaces(&desc);
    524                
    525                 /* Get rid of root namespace */
    526                 size_t i;
    527                 for (i = 0; i < count; i++) {
    528                         if (str_cmp(desc[i].name, "") == 0) {
    529                                 if (pos >= i)
    530                                         pos++;
    531                                
    532                                 break;
    533                         }
    534                 }
    535                
    536                 if (pos < count) {
    537                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    538                         free(desc);
    539                         async_answer_1(rid, EOK, 1);
    540                         return;
    541                 }
    542                
    543                 free(desc);
    544                 pos -= count;
    545                
    546                 /* Search root namespace */
    547                 devmap_handle_t namespace;
    548                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    549                         count = devmap_get_devices(namespace, &desc);
    550                        
    551                         if (pos < count) {
    552                                 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    553                                 free(desc);
    554                                 async_answer_1(rid, EOK, 1);
     142        ipcarg_t first = IPC_GET_ARG1(*request);
     143        ipcarg_t last = IPC_GET_ARG2(*request);
     144        dev_handle_t dev_handle = IPC_GET_ARG3(*request);
     145        ipcarg_t lflag = IPC_GET_ARG4(*request);
     146        fs_index_t index = IPC_GET_ARG5(*request);
     147       
     148        /* Hierarchy is flat, no altroot is supported */
     149        if (index != 0) {
     150                ipc_answer_0(rid, ENOENT);
     151                return;
     152        }
     153       
     154        if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
     155                ipc_answer_0(rid, ENOTSUP);
     156                return;
     157        }
     158       
     159        /* Eat slash */
     160        if (PLB_GET_CHAR(first) == '/') {
     161                first++;
     162                first %= PLB_SIZE;
     163        }
     164       
     165        if (first >= last) {
     166                /* Root entry */
     167                if (!(lflag & L_FILE))
     168                        ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
     169                else
     170                        ipc_answer_0(rid, ENOENT);
     171        } else {
     172                if (!(lflag & L_DIRECTORY)) {
     173                        size_t len;
     174                        if (last >= first)
     175                                len = last - first + 1;
     176                        else
     177                                len = first + PLB_SIZE - last + 1;
     178                       
     179                        char *name = (char *) malloc(len + 1);
     180                        if (name == NULL) {
     181                                ipc_answer_0(rid, ENOMEM);
    555182                                return;
    556183                        }
    557184                       
    558                         free(desc);
    559                 }
    560                
    561                 async_answer_0(callid, ENOENT);
    562                 async_answer_1(rid, ENOENT, 0);
     185                        size_t i;
     186                        for (i = 0; i < len; i++)
     187                                name[i] = PLB_GET_CHAR(first + i);
     188                       
     189                        name[len] = 0;
     190                       
     191                        dev_handle_t handle;
     192                        if (devmap_device_get_handle(name, &handle, 0) != EOK) {
     193                                free(name);
     194                                ipc_answer_0(rid, ENOENT);
     195                                return;
     196                        }
     197                       
     198                        if (lflag & L_OPEN) {
     199                                unsigned long key[] = {
     200                                        [DEVICES_KEY_HANDLE] = (unsigned long) handle
     201                                };
     202                               
     203                                fibril_mutex_lock(&devices_mutex);
     204                                link_t *lnk = hash_table_find(&devices, key);
     205                                if (lnk == NULL) {
     206                                        int phone = devmap_device_connect(handle, 0);
     207                                        if (phone < 0) {
     208                                                fibril_mutex_unlock(&devices_mutex);
     209                                                free(name);
     210                                                ipc_answer_0(rid, ENOENT);
     211                                                return;
     212                                        }
     213                                       
     214                                        device_t *dev = (device_t *) malloc(sizeof(device_t));
     215                                        if (dev == NULL) {
     216                                                fibril_mutex_unlock(&devices_mutex);
     217                                                free(name);
     218                                                ipc_answer_0(rid, ENOMEM);
     219                                                return;
     220                                        }
     221                                       
     222                                        dev->handle = handle;
     223                                        dev->phone = phone;
     224                                        dev->refcount = 1;
     225                                       
     226                                        hash_table_insert(&devices, key, &dev->link);
     227                                } else {
     228                                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
     229                                        dev->refcount++;
     230                                }
     231                                fibril_mutex_unlock(&devices_mutex);
     232                        }
     233                       
     234                        free(name);
     235                       
     236                        ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
     237                } else
     238                        ipc_answer_0(rid, ENOENT);
     239        }
     240}
     241
     242void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     243{
     244        dev_handle_t handle = IPC_GET_ARG2(*request);
     245       
     246        unsigned long key[] = {
     247                [DEVICES_KEY_HANDLE] = (unsigned long) handle
     248        };
     249       
     250        fibril_mutex_lock(&devices_mutex);
     251        link_t *lnk = hash_table_find(&devices, key);
     252        if (lnk == NULL) {
     253                int phone = devmap_device_connect(handle, 0);
     254                if (phone < 0) {
     255                        fibril_mutex_unlock(&devices_mutex);
     256                        ipc_answer_0(rid, ENOENT);
     257                        return;
     258                }
     259               
     260                device_t *dev = (device_t *) malloc(sizeof(device_t));
     261                if (dev == NULL) {
     262                        fibril_mutex_unlock(&devices_mutex);
     263                        ipc_answer_0(rid, ENOMEM);
     264                        return;
     265                }
     266               
     267                dev->handle = handle;
     268                dev->phone = phone;
     269                dev->refcount = 1;
     270               
     271                hash_table_insert(&devices, key, &dev->link);
     272        } else {
     273                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     274                dev->refcount++;
     275        }
     276        fibril_mutex_unlock(&devices_mutex);
     277       
     278        ipc_answer_3(rid, EOK, 0, 1, L_FILE);
     279}
     280
     281void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
     282{
     283        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     284        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     285       
     286        ipc_callid_t callid;
     287        size_t size;
     288        if (!ipc_data_read_receive(&callid, &size) ||
     289            size != sizeof(struct stat)) {
     290                ipc_answer_0(callid, EINVAL);
     291                ipc_answer_0(rid, EINVAL);
    563292                return;
    564293        }
    565        
    566         devmap_handle_type_t type = devmap_handle_probe(index);
    567        
    568         if (type == DEV_HANDLE_NAMESPACE) {
    569                 /* Namespace directory */
    570                 ipc_callid_t callid;
    571                 size_t size;
    572                 if (!async_data_read_receive(&callid, &size)) {
    573                         async_answer_0(callid, EINVAL);
    574                         async_answer_0(rid, EINVAL);
    575                         return;
    576                 }
    577                
    578                 dev_desc_t *desc;
    579                 size_t count = devmap_get_devices(index, &desc);
    580                
    581                 if (pos < count) {
    582                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    583                         free(desc);
    584                         async_answer_1(rid, EOK, 1);
    585                         return;
    586                 }
    587                
    588                 free(desc);
    589                 async_answer_0(callid, ENOENT);
    590                 async_answer_1(rid, ENOENT, 0);
    591                 return;
    592         }
    593        
    594         if (type == DEV_HANDLE_DEVICE) {
    595                 /* Device node */
    596                
     294
     295        struct stat stat;
     296        memset(&stat, 0, sizeof(struct stat));
     297
     298        stat.fs_handle = devfs_reg.fs_handle;
     299        stat.dev_handle = dev_handle;
     300        stat.index = index;
     301        stat.lnkcnt = 1;
     302        stat.is_file = (index != 0);
     303        stat.size = 0;
     304       
     305        if (index != 0) {
    597306                unsigned long key[] = {
    598307                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    601310                fibril_mutex_lock(&devices_mutex);
    602311                link_t *lnk = hash_table_find(&devices, key);
    603                 if (lnk == NULL) {
    604                         fibril_mutex_unlock(&devices_mutex);
    605                         async_answer_0(rid, ENOENT);
    606                         return;
    607                 }
    608                
    609                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
    610                 assert(dev->phone >= 0);
    611                
    612                 ipc_callid_t callid;
    613                 if (!async_data_read_receive(&callid, NULL)) {
    614                         fibril_mutex_unlock(&devices_mutex);
    615                         async_answer_0(callid, EINVAL);
    616                         async_answer_0(rid, EINVAL);
    617                         return;
    618                 }
    619                
    620                 /* Make a request at the driver */
    621                 ipc_call_t answer;
    622                 aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
    623                     IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
    624                     IPC_GET_ARG3(*request), &answer);
    625                
    626                 /* Forward the IPC_M_DATA_READ request to the driver */
    627                 async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     312                if (lnk != NULL)
     313                        stat.devfs_stat.device = (dev_handle_t)index;
    628314                fibril_mutex_unlock(&devices_mutex);
    629                
    630                 /* Wait for reply from the driver. */
    631                 sysarg_t rc;
    632                 async_wait_for(msg, &rc);
    633                 size_t bytes = IPC_GET_ARG1(answer);
    634                
    635                 /* Driver reply is the final result of the whole operation */
    636                 async_answer_1(rid, rc, bytes);
    637                 return;
    638         }
    639        
    640         async_answer_0(rid, ENOENT);
    641 }
    642 
    643 void devfs_write(ipc_callid_t rid, ipc_call_t *request)
     315        }
     316
     317        ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
     318        ipc_answer_0(rid, EOK);
     319}
     320
     321void devfs_read(ipc_callid_t rid, ipc_call_t *request)
    644322{
    645323        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    646         if (index == 0) {
    647                 async_answer_0(rid, ENOTSUP);
    648                 return;
    649         }
    650        
    651         devmap_handle_type_t type = devmap_handle_probe(index);
    652        
    653         if (type == DEV_HANDLE_NAMESPACE) {
    654                 /* Namespace directory */
    655                 async_answer_0(rid, ENOTSUP);
    656                 return;
    657         }
    658        
    659         if (type == DEV_HANDLE_DEVICE) {
    660                 /* Device node */
     324        off_t pos = (off_t) IPC_GET_ARG3(*request);
     325       
     326        if (index != 0) {
    661327                unsigned long key[] = {
    662328                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    667333                if (lnk == NULL) {
    668334                        fibril_mutex_unlock(&devices_mutex);
    669                         async_answer_0(rid, ENOENT);
     335                        ipc_answer_0(rid, ENOENT);
    670336                        return;
    671337                }
    672338               
    673339                device_t *dev = hash_table_get_instance(lnk, device_t, link);
    674                 assert(dev->phone >= 0);
    675340               
    676341                ipc_callid_t callid;
    677                 if (!async_data_write_receive(&callid, NULL)) {
    678                         fibril_mutex_unlock(&devices_mutex);
    679                         async_answer_0(callid, EINVAL);
    680                         async_answer_0(rid, EINVAL);
     342                if (!ipc_data_read_receive(&callid, NULL)) {
     343                        fibril_mutex_unlock(&devices_mutex);
     344                        ipc_answer_0(callid, EINVAL);
     345                        ipc_answer_0(rid, EINVAL);
    681346                        return;
    682347                }
     
    684349                /* Make a request at the driver */
    685350                ipc_call_t answer;
    686                 aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
     351                aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
    687352                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
    688353                    IPC_GET_ARG3(*request), &answer);
    689354               
    690                 /* Forward the IPC_M_DATA_WRITE request to the driver */
    691                 async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    692                
     355                /* Forward the IPC_M_DATA_READ request to the driver */
     356                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    693357                fibril_mutex_unlock(&devices_mutex);
    694358               
    695359                /* Wait for reply from the driver. */
    696                 sysarg_t rc;
     360                ipcarg_t rc;
    697361                async_wait_for(msg, &rc);
    698362                size_t bytes = IPC_GET_ARG1(answer);
    699363               
    700364                /* Driver reply is the final result of the whole operation */
    701                 async_answer_1(rid, rc, bytes);
    702                 return;
    703         }
    704        
    705         async_answer_0(rid, ENOENT);
    706 }
    707 
    708 void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
    709 {
    710         async_answer_0(rid, ENOTSUP);
    711 }
    712 
    713 void devfs_close(ipc_callid_t rid, ipc_call_t *request)
     365                ipc_answer_1(rid, rc, bytes);
     366        } else {
     367                ipc_callid_t callid;
     368                size_t size;
     369                if (!ipc_data_read_receive(&callid, &size)) {
     370                        ipc_answer_0(callid, EINVAL);
     371                        ipc_answer_0(rid, EINVAL);
     372                        return;
     373                }
     374               
     375                size_t count = devmap_device_get_count();
     376                dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
     377                if (desc == NULL) {
     378                        ipc_answer_0(callid, ENOMEM);
     379                        ipc_answer_1(rid, ENOMEM, 0);
     380                        return;
     381                }
     382               
     383                size_t max = devmap_device_get_devices(count, desc);
     384               
     385                if (pos < max) {
     386                        ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
     387                } else {
     388                        ipc_answer_0(callid, ENOENT);
     389                        ipc_answer_1(rid, ENOENT, 0);
     390                        return;
     391                }
     392               
     393                free(desc);
     394               
     395                ipc_answer_1(rid, EOK, 1);
     396        }
     397}
     398
     399void devfs_write(ipc_callid_t rid, ipc_call_t *request)
    714400{
    715401        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    716        
    717         if (index == 0) {
    718                 async_answer_0(rid, EOK);
    719                 return;
    720         }
    721        
    722         devmap_handle_type_t type = devmap_handle_probe(index);
    723        
    724         if (type == DEV_HANDLE_NAMESPACE) {
    725                 /* Namespace directory */
    726                 async_answer_0(rid, EOK);
    727                 return;
    728         }
    729        
    730         if (type == DEV_HANDLE_DEVICE) {
     402        off_t pos = (off_t) IPC_GET_ARG3(*request);
     403       
     404        if (index != 0) {
    731405                unsigned long key[] = {
    732406                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    737411                if (lnk == NULL) {
    738412                        fibril_mutex_unlock(&devices_mutex);
    739                         async_answer_0(rid, ENOENT);
     413                        ipc_answer_0(rid, ENOENT);
    740414                        return;
    741415                }
    742416               
    743417                device_t *dev = hash_table_get_instance(lnk, device_t, link);
    744                 assert(dev->phone >= 0);
    745                 dev->refcount--;
    746                
    747                 if (dev->refcount == 0) {
    748                         async_hangup(dev->phone);
    749                         hash_table_remove(&devices, key, DEVICES_KEYS);
    750                 }
     418               
     419                ipc_callid_t callid;
     420                if (!ipc_data_write_receive(&callid, NULL)) {
     421                        fibril_mutex_unlock(&devices_mutex);
     422                        ipc_answer_0(callid, EINVAL);
     423                        ipc_answer_0(rid, EINVAL);
     424                        return;
     425                }
     426               
     427                /* Make a request at the driver */
     428                ipc_call_t answer;
     429                aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
     430                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
     431                    IPC_GET_ARG3(*request), &answer);
     432               
     433                /* Forward the IPC_M_DATA_WRITE request to the driver */
     434                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    751435               
    752436                fibril_mutex_unlock(&devices_mutex);
    753437               
    754                 async_answer_0(rid, EOK);
    755                 return;
    756         }
    757        
    758         async_answer_0(rid, ENOENT);
    759 }
    760 
    761 void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
     438                /* Wait for reply from the driver. */
     439                ipcarg_t rc;
     440                async_wait_for(msg, &rc);
     441                size_t bytes = IPC_GET_ARG1(answer);
     442               
     443                /* Driver reply is the final result of the whole operation */
     444                ipc_answer_1(rid, rc, bytes);
     445        } else {
     446                /* Read-only filesystem */
     447                ipc_answer_0(rid, ENOTSUP);
     448        }
     449}
     450
     451void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
     452{
     453        ipc_answer_0(rid, ENOTSUP);
     454}
     455
     456void devfs_close(ipc_callid_t rid, ipc_call_t *request)
    762457{
    763458        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    764459       
    765         if (index == 0) {
    766                 async_answer_0(rid, EOK);
    767                 return;
    768         }
    769        
    770         devmap_handle_type_t type = devmap_handle_probe(index);
    771        
    772         if (type == DEV_HANDLE_NAMESPACE) {
    773                 /* Namespace directory */
    774                 async_answer_0(rid, EOK);
    775                 return;
    776         }
    777        
    778         if (type == DEV_HANDLE_DEVICE) {
     460        if (index != 0) {
    779461                unsigned long key[] = {
    780462                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    785467                if (lnk == NULL) {
    786468                        fibril_mutex_unlock(&devices_mutex);
    787                         async_answer_0(rid, ENOENT);
     469                        ipc_answer_0(rid, ENOENT);
    788470                        return;
    789471                }
    790472               
    791473                device_t *dev = hash_table_get_instance(lnk, device_t, link);
    792                 assert(dev->phone >= 0);
     474                dev->refcount--;
     475               
     476                if (dev->refcount == 0) {
     477                        ipc_hangup(dev->phone);
     478                        hash_table_remove(&devices, key, DEVICES_KEYS);
     479                }
     480               
     481                fibril_mutex_unlock(&devices_mutex);
     482               
     483                ipc_answer_0(rid, EOK);
     484        } else
     485                ipc_answer_0(rid, ENOTSUP);
     486}
     487
     488void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
     489{
     490        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     491       
     492        if (index != 0) {
     493                unsigned long key[] = {
     494                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     495                };
     496               
     497                fibril_mutex_lock(&devices_mutex);
     498                link_t *lnk = hash_table_find(&devices, key);
     499                if (lnk == NULL) {
     500                        fibril_mutex_unlock(&devices_mutex);
     501                        ipc_answer_0(rid, ENOENT);
     502                        return;
     503                }
     504               
     505                device_t *dev = hash_table_get_instance(lnk, device_t, link);
    793506               
    794507                /* Make a request at the driver */
    795508                ipc_call_t answer;
    796                 aid_t msg = async_send_2(dev->phone, IPC_GET_IMETHOD(*request),
     509                aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request),
    797510                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
    798511               
     
    800513               
    801514                /* Wait for reply from the driver */
    802                 sysarg_t rc;
     515                ipcarg_t rc;
    803516                async_wait_for(msg, &rc);
    804517               
    805518                /* Driver reply is the final result of the whole operation */
    806                 async_answer_0(rid, rc);
    807                 return;
    808         }
    809        
    810         async_answer_0(rid, ENOENT);
     519                ipc_answer_0(rid, rc);
     520        } else
     521                ipc_answer_0(rid, ENOTSUP);
    811522}
    812523
    813524void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
    814525{
    815         async_answer_0(rid, ENOTSUP);
     526        ipc_answer_0(rid, ENOTSUP);
    816527}
    817528
Note: See TracChangeset for help on using the changeset viewer.