Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/devman.c

    rb72efe8 re72fb34  
    3535 */
    3636
    37 #include <adt/list.h>
    3837#include <str.h>
     38#include <stdio.h>
    3939#include <ipc/services.h>
    40 #include <ns.h>
    4140#include <ipc/devman.h>
    4241#include <devman.h>
     42#include <async.h>
    4343#include <fibril_synch.h>
    44 #include <async.h>
    4544#include <errno.h>
    4645#include <malloc.h>
    4746#include <bool.h>
    48 
    49 static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
    50 static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
    51 
    52 static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
    53 static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
    54 
    55 static async_sess_t *devman_driver_block_sess = NULL;
    56 static async_sess_t *devman_client_block_sess = NULL;
    57 
    58 static async_sess_t *devman_driver_sess = NULL;
    59 static async_sess_t *devman_client_sess = NULL;
    60 
    61 static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
    62     async_sess_t **dst)
    63 {
    64         fibril_mutex_lock(mtx);
    65        
    66         if ((*dst == NULL) && (src != NULL))
    67                 *dst = src;
    68        
    69         fibril_mutex_unlock(mtx);
    70 }
    71 
    72 /** Start an async exchange on the devman session (blocking).
    73  *
    74  * @param iface Device manager interface to choose
    75  *
    76  * @return New exchange.
    77  *
    78  */
    79 async_exch_t *devman_exchange_begin_blocking(devman_interface_t iface)
     47#include <adt/list.h>
     48
     49static int devman_phone_driver = -1;
     50static int devman_phone_client = -1;
     51
     52static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
     53
     54int devman_get_phone(devman_interface_t iface, unsigned int flags)
    8055{
    8156        switch (iface) {
    8257        case DEVMAN_DRIVER:
    83                 fibril_mutex_lock(&devman_driver_block_mutex);
     58                fibril_mutex_lock(&devman_phone_mutex);
     59                if (devman_phone_driver >= 0) {
     60                        fibril_mutex_unlock(&devman_phone_mutex);
     61                        return devman_phone_driver;
     62                }
    8463               
    85                 while (devman_driver_block_sess == NULL) {
    86                         clone_session(&devman_driver_mutex, devman_driver_sess,
    87                             &devman_driver_block_sess);
    88                        
    89                         if (devman_driver_block_sess == NULL)
    90                                 devman_driver_block_sess =
    91                                     service_connect_blocking(EXCHANGE_SERIALIZE,
    92                                     SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    93                 }
     64                if (flags & IPC_FLAG_BLOCKING)
     65                        devman_phone_driver = async_connect_me_to_blocking(
     66                            PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
     67                else
     68                        devman_phone_driver = async_connect_me_to(PHONE_NS,
     69                            SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    9470               
    95                 fibril_mutex_unlock(&devman_driver_block_mutex);
     71                fibril_mutex_unlock(&devman_phone_mutex);
     72                return devman_phone_driver;
     73        case DEVMAN_CLIENT:
     74                fibril_mutex_lock(&devman_phone_mutex);
     75                if (devman_phone_client >= 0) {
     76                        fibril_mutex_unlock(&devman_phone_mutex);
     77                        return devman_phone_client;
     78                }
    9679               
    97                 clone_session(&devman_driver_mutex, devman_driver_block_sess,
    98                     &devman_driver_sess);
     80                if (flags & IPC_FLAG_BLOCKING) {
     81                        devman_phone_client = async_connect_me_to_blocking(
     82                            PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
     83                } else {
     84                        devman_phone_client = async_connect_me_to(PHONE_NS,
     85                            SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
     86                }
    9987               
    100                 return async_exchange_begin(devman_driver_block_sess);
    101         case DEVMAN_CLIENT:
    102                 fibril_mutex_lock(&devman_client_block_mutex);
    103                
    104                 while (devman_client_block_sess == NULL) {
    105                         clone_session(&devman_client_mutex, devman_client_sess,
    106                             &devman_client_block_sess);
    107                        
    108                         if (devman_client_block_sess == NULL)
    109                                 devman_client_block_sess =
    110                                     service_connect_blocking(EXCHANGE_SERIALIZE,
    111                                     SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
    112                 }
    113                
    114                 fibril_mutex_unlock(&devman_client_block_mutex);
    115                
    116                 clone_session(&devman_client_mutex, devman_client_block_sess,
    117                     &devman_client_sess);
    118                
    119                 return async_exchange_begin(devman_client_block_sess);
     88                fibril_mutex_unlock(&devman_phone_mutex);
     89                return devman_phone_client;
    12090        default:
    121                 return NULL;
    122         }
    123 }
    124 
    125 /** Start an async exchange on the devman session.
    126  *
    127  * @param iface Device manager interface to choose
    128  *
    129  * @return New exchange.
    130  *
    131  */
    132 async_exch_t *devman_exchange_begin(devman_interface_t iface)
     91                return -1;
     92        }
     93}
     94
     95/** Register running driver with device manager. */
     96int devman_driver_register(const char *name, async_client_conn_t conn)
     97{
     98        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     99       
     100        if (phone < 0)
     101                return phone;
     102       
     103        async_serialize_start();
     104       
     105        ipc_call_t answer;
     106        aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
     107       
     108        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     109        if (retval != EOK) {
     110                async_wait_for(req, NULL);
     111                async_serialize_end();
     112                return -1;
     113        }
     114       
     115        async_set_client_connection(conn);
     116       
     117        async_connect_to_me(phone, 0, 0, 0, NULL);
     118        async_wait_for(req, &retval);
     119       
     120        async_serialize_end();
     121       
     122        return retval;
     123}
     124
     125static int devman_send_match_id(int phone, match_id_t *match_id)
     126{
     127        ipc_call_t answer;
     128
     129        aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
     130            &answer);
     131        int retval = async_data_write_start(phone, match_id->id,
     132            str_size(match_id->id));
     133
     134        async_wait_for(req, NULL);
     135        return retval;
     136}
     137
     138
     139static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
     140{
     141        link_t *link = match_ids->ids.next;
     142        match_id_t *match_id = NULL;
     143        int ret = EOK;
     144
     145        while (link != &match_ids->ids) {
     146                match_id = list_get_instance(link, match_id_t, link);
     147                ret = devman_send_match_id(phone, match_id);
     148                if (ret != EOK) {
     149                        return ret;
     150                }
     151
     152                link = link->next;
     153        }
     154
     155        return ret;
     156}
     157
     158/** Add function to a device.
     159 *
     160 * Request devman to add a new function to the specified device owned by
     161 * this driver task.
     162 *
     163 * @param name          Name of the new function
     164 * @param ftype         Function type, fun_inner or fun_exposed
     165 * @param match_ids     Match IDs (should be empty for fun_exposed)
     166 * @param devh          Devman handle of the device
     167 * @param funh          Place to store handle of the new function
     168 *
     169 * @return              EOK on success or negative error code.
     170 */
     171int devman_add_function(const char *name, fun_type_t ftype,
     172    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
     173{
     174        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     175        int fun_handle;
     176       
     177        if (phone < 0)
     178                return phone;
     179       
     180        async_serialize_start();
     181       
     182        int match_count = list_count(&match_ids->ids);
     183        ipc_call_t answer;
     184
     185        aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
     186            devh, match_count, &answer);
     187
     188        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     189        if (retval != EOK) {
     190                async_wait_for(req, NULL);
     191                async_serialize_end();
     192                return retval;
     193        }
     194       
     195        int match_ids_rc = devman_send_match_ids(phone, match_ids);
     196       
     197        async_wait_for(req, &retval);
     198       
     199        async_serialize_end();
     200       
     201        /* Prefer the answer to DEVMAN_ADD_FUNCTION in case of errors. */
     202        if ((match_ids_rc != EOK) && (retval == EOK)) {
     203                retval = match_ids_rc;
     204        }
     205
     206        if (retval == EOK)
     207                fun_handle = (int) IPC_GET_ARG1(answer);
     208        else
     209                fun_handle = -1;
     210       
     211        *funh = fun_handle;
     212
     213        return retval;
     214}
     215
     216int devman_add_device_to_class(devman_handle_t devman_handle,
     217    const char *class_name)
     218{
     219        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     220       
     221        if (phone < 0)
     222                return phone;
     223       
     224        async_serialize_start();
     225        ipc_call_t answer;
     226        aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
     227            devman_handle, &answer);
     228       
     229        sysarg_t retval = async_data_write_start(phone, class_name,
     230            str_size(class_name));
     231        if (retval != EOK) {
     232                async_wait_for(req, NULL);
     233                async_serialize_end();
     234                return retval;
     235        }
     236       
     237        async_wait_for(req, &retval);
     238        async_serialize_end();
     239       
     240        return retval;
     241}
     242
     243void devman_hangup_phone(devman_interface_t iface)
    133244{
    134245        switch (iface) {
    135246        case DEVMAN_DRIVER:
    136                 fibril_mutex_lock(&devman_driver_mutex);
    137                
    138                 if (devman_driver_sess == NULL)
    139                         devman_driver_sess =
    140                             service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
    141                             DEVMAN_DRIVER, 0);
    142                
    143                 fibril_mutex_unlock(&devman_driver_mutex);
    144                
    145                 if (devman_driver_sess == NULL)
    146                         return NULL;
    147                
    148                 return async_exchange_begin(devman_driver_sess);
     247                if (devman_phone_driver >= 0) {
     248                        async_hangup(devman_phone_driver);
     249                        devman_phone_driver = -1;
     250                }
     251                break;
    149252        case DEVMAN_CLIENT:
    150                 fibril_mutex_lock(&devman_client_mutex);
    151                
    152                 if (devman_client_sess == NULL)
    153                         devman_client_sess =
    154                             service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
    155                             DEVMAN_CLIENT, 0);
    156                
    157                 fibril_mutex_unlock(&devman_client_mutex);
    158                
    159                 if (devman_client_sess == NULL)
    160                         return NULL;
    161                
    162                 return async_exchange_begin(devman_client_sess);
     253                if (devman_phone_client >= 0) {
     254                        async_hangup(devman_phone_client);
     255                        devman_phone_client = -1;
     256                }
     257                break;
    163258        default:
    164                 return NULL;
    165         }
    166 }
    167 
    168 /** Finish an async exchange on the devman session.
    169  *
    170  * @param exch Exchange to be finished.
    171  *
    172  */
    173 void devman_exchange_end(async_exch_t *exch)
    174 {
    175         async_exchange_end(exch);
    176 }
    177 
    178 /** Register running driver with device manager. */
    179 int devman_driver_register(const char *name, async_client_conn_t conn)
    180 {
    181         async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    182        
    183         ipc_call_t answer;
    184         aid_t req = async_send_2(exch, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
    185         sysarg_t retval = async_data_write_start(exch, name, str_size(name));
    186        
    187         devman_exchange_end(exch);
    188        
    189         if (retval != EOK) {
    190                 async_wait_for(req, NULL);
    191                 return retval;
    192         }
    193        
    194         async_set_client_connection(conn);
    195        
    196         exch = devman_exchange_begin(DEVMAN_DRIVER);
    197         async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
    198         devman_exchange_end(exch);
    199        
    200         async_wait_for(req, &retval);
    201         return retval;
    202 }
    203 
    204 /** Add function to a device.
    205  *
    206  * Request devman to add a new function to the specified device owned by
    207  * this driver task.
    208  *
    209  * @param name      Name of the new function
    210  * @param ftype     Function type, fun_inner or fun_exposed
    211  * @param match_ids Match IDs (should be empty for fun_exposed)
    212  * @param devh      Devman handle of the device
    213  * @param funh      Place to store handle of the new function
    214  *
    215  * @return EOK on success or negative error code.
    216  *
    217  */
    218 int devman_add_function(const char *name, fun_type_t ftype,
    219     match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
    220 {
    221         int match_count = list_count(&match_ids->ids);
    222         async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    223        
    224         ipc_call_t answer;
    225         aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
    226             devh, match_count, &answer);
    227         sysarg_t retval = async_data_write_start(exch, name, str_size(name));
    228         if (retval != EOK) {
    229                 devman_exchange_end(exch);
    230                 async_wait_for(req, NULL);
    231                 return retval;
    232         }
    233        
    234         match_id_t *match_id = NULL;
    235        
    236         list_foreach(match_ids->ids, link) {
    237                 match_id = list_get_instance(link, match_id_t, link);
    238                
    239                 ipc_call_t answer2;
    240                 aid_t req2 = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
    241                     match_id->score, &answer2);
    242                 retval = async_data_write_start(exch, match_id->id,
    243                     str_size(match_id->id));
    244                 if (retval != EOK) {
    245                         devman_exchange_end(exch);
    246                         async_wait_for(req2, NULL);
    247                         async_wait_for(req, NULL);
    248                         return retval;
    249                 }
    250                
    251                 async_wait_for(req2, &retval);
    252                 if (retval != EOK) {
    253                         devman_exchange_end(exch);
    254                         async_wait_for(req, NULL);
    255                         return retval;
    256                 }
    257         }
    258        
    259         devman_exchange_end(exch);
    260        
    261         async_wait_for(req, &retval);
    262         if (retval == EOK) {
    263                 if (funh != NULL)
    264                         *funh = (int) IPC_GET_ARG1(answer);
     259                break;
     260        }
     261}
     262
     263int devman_device_connect(devman_handle_t handle, unsigned int flags)
     264{
     265        int phone;
     266       
     267        if (flags & IPC_FLAG_BLOCKING) {
     268                phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
     269                    DEVMAN_CONNECT_TO_DEVICE, handle);
    265270        } else {
    266                 if (funh != NULL)
    267                         *funh = -1;
    268         }
    269        
    270         return retval;
    271 }
    272 
    273 int devman_add_device_to_class(devman_handle_t devman_handle,
    274     const char *class_name)
    275 {
    276         async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    277        
    278         ipc_call_t answer;
    279         aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CLASS,
    280             devman_handle, &answer);
    281         sysarg_t retval = async_data_write_start(exch, class_name,
    282             str_size(class_name));
    283        
    284         devman_exchange_end(exch);
    285        
    286         if (retval != EOK) {
    287                 async_wait_for(req, NULL);
    288                 return retval;
    289         }
    290        
    291         async_wait_for(req, &retval);
    292         return retval;
    293 }
    294 
    295 async_sess_t *devman_device_connect(exch_mgmt_t mgmt, devman_handle_t handle,
    296     unsigned int flags)
    297 {
    298         async_sess_t *sess;
    299        
    300         if (flags & IPC_FLAG_BLOCKING)
    301                 sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
    302                             DEVMAN_CONNECT_TO_DEVICE, handle);
    303         else
    304                 sess = service_connect(mgmt, SERVICE_DEVMAN,
    305                             DEVMAN_CONNECT_TO_DEVICE, handle);
    306        
    307         return sess;
    308 }
    309 
    310 async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
    311     devman_handle_t handle, unsigned int flags)
    312 {
    313         async_sess_t *sess;
    314        
    315         if (flags & IPC_FLAG_BLOCKING)
    316                 sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
    317                             DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    318         else
    319                 sess = service_connect(mgmt, SERVICE_DEVMAN,
    320                             DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    321        
    322         return sess;
     271                phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
     272                    DEVMAN_CONNECT_TO_DEVICE, handle);
     273        }
     274       
     275        return phone;
     276}
     277
     278int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
     279{
     280        int phone;
     281       
     282        if (flags & IPC_FLAG_BLOCKING) {
     283                phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
     284                    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     285        } else {
     286                phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
     287                    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     288        }
     289       
     290        return phone;
    323291}
    324292
     
    326294    unsigned int flags)
    327295{
    328         async_exch_t *exch;
    329        
    330         if (flags & IPC_FLAG_BLOCKING)
    331                 exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
    332         else {
    333                 exch = devman_exchange_begin(DEVMAN_CLIENT);
    334                 if (exch == NULL)
    335                         return errno;
    336         }
    337        
    338         ipc_call_t answer;
    339         aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
     296        int phone = devman_get_phone(DEVMAN_CLIENT, flags);
     297       
     298        if (phone < 0)
     299                return phone;
     300       
     301        async_serialize_start();
     302       
     303        ipc_call_t answer;
     304        aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
    340305            &answer);
    341         sysarg_t retval = async_data_write_start(exch, pathname,
     306       
     307        sysarg_t retval = async_data_write_start(phone, pathname,
    342308            str_size(pathname));
    343        
    344         devman_exchange_end(exch);
    345        
    346         if (retval != EOK) {
    347                 async_wait_for(req, NULL);
    348                 return retval;
    349         }
    350        
    351         async_wait_for(req, &retval);
     309        if (retval != EOK) {
     310                async_wait_for(req, NULL);
     311                async_serialize_end();
     312                return retval;
     313        }
     314       
     315        async_wait_for(req, &retval);
     316       
     317        async_serialize_end();
    352318       
    353319        if (retval != EOK) {
    354320                if (handle != NULL)
    355321                        *handle = (devman_handle_t) -1;
    356                
    357322                return retval;
    358323        }
     
    367332    const char *devname, devman_handle_t *handle, unsigned int flags)
    368333{
    369         async_exch_t *exch;
    370        
    371         if (flags & IPC_FLAG_BLOCKING)
    372                 exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
    373         else {
    374                 exch = devman_exchange_begin(DEVMAN_CLIENT);
    375                 if (exch == NULL)
    376                         return errno;
    377         }
    378        
    379         ipc_call_t answer;
    380         aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
     334        int phone = devman_get_phone(DEVMAN_CLIENT, flags);
     335
     336        if (phone < 0)
     337                return phone;
     338
     339        async_serialize_start();
     340
     341        ipc_call_t answer;
     342        aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
    381343            flags, &answer);
    382         sysarg_t retval = async_data_write_start(exch, classname,
     344
     345        sysarg_t retval = async_data_write_start(phone, classname,
    383346            str_size(classname));
    384        
    385         if (retval != EOK) {
    386                 devman_exchange_end(exch);
    387                 async_wait_for(req, NULL);
    388                 return retval;
    389         }
    390        
    391         retval = async_data_write_start(exch, devname,
     347        if (retval != EOK) {
     348                async_wait_for(req, NULL);
     349                async_serialize_end();
     350                return retval;
     351        }
     352        retval = async_data_write_start(phone, devname,
    392353            str_size(devname));
    393        
    394         devman_exchange_end(exch);
    395        
    396         if (retval != EOK) {
    397                 async_wait_for(req, NULL);
    398                 return retval;
    399         }
    400        
    401         async_wait_for(req, &retval);
    402        
     354        if (retval != EOK) {
     355                async_wait_for(req, NULL);
     356                async_serialize_end();
     357                return retval;
     358        }
     359
     360        async_wait_for(req, &retval);
     361
     362        async_serialize_end();
     363
    403364        if (retval != EOK) {
    404365                if (handle != NULL)
    405366                        *handle = (devman_handle_t) -1;
    406                
    407                 return retval;
    408         }
    409        
     367                return retval;
     368        }
     369
    410370        if (handle != NULL)
    411371                *handle = (devman_handle_t) IPC_GET_ARG1(answer);
    412        
    413         return retval;
    414 }
    415 
    416 int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
    417 {
    418         async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
    419         if (exch == NULL)
    420                 return errno;
    421        
    422         ipc_call_t answer;
    423         aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_DEVICE_PATH,
    424             handle, &answer);
    425        
    426         ipc_call_t data_request_call;
    427         aid_t data_request = async_data_read(exch, path, path_size,
    428             &data_request_call);
    429        
    430         devman_exchange_end(exch);
    431        
    432         if (data_request == 0) {
    433                 async_wait_for(req, NULL);
    434                 return ENOMEM;
    435         }
    436        
    437         sysarg_t data_request_rc;
    438         async_wait_for(data_request, &data_request_rc);
    439        
    440         sysarg_t opening_request_rc;
    441         async_wait_for(req, &opening_request_rc);
    442        
    443         if (data_request_rc != EOK) {
    444                 /* Prefer the return code of the opening request. */
    445                 if (opening_request_rc != EOK)
    446                         return (int) opening_request_rc;
    447                 else
    448                         return (int) data_request_rc;
    449         }
    450        
    451         if (opening_request_rc != EOK)
    452                 return (int) opening_request_rc;
    453        
    454         /* To be on the safe-side. */
    455         path[path_size - 1] = 0;
    456         size_t transferred_size = IPC_GET_ARG2(data_request_call);
    457         if (transferred_size >= path_size)
    458                 return ELIMIT;
    459        
    460         /* Terminate the string (trailing 0 not send over IPC). */
    461         path[transferred_size] = 0;
    462         return EOK;
    463 }
     372
     373        return retval;
     374}
     375
    464376
    465377/** @}
Note: See TracChangeset for help on using the changeset viewer.