Subversion Repositories HelenOS

Rev

Rev 2741 | Rev 2755 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <vfs.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <dirent.h>
  39. #include <fcntl.h>
  40. #include <sys/stat.h>
  41. #include <sys/types.h>
  42. #include <ipc/ipc.h>
  43. #include <ipc/services.h>
  44. #include <async.h>
  45. #include <atomic.h>
  46. #include <futex.h>
  47. #include <errno.h>
  48. #include <string.h>
  49. #include "../../srv/vfs/vfs.h"
  50.  
  51. int vfs_phone = -1;
  52. atomic_t vfs_phone_futex = FUTEX_INITIALIZER;
  53.  
  54. static int vfs_connect(void)
  55. {
  56.     if (vfs_phone < 0)
  57.         vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
  58.     return vfs_phone;
  59. }
  60.  
  61. int mount(const char *fs_name, const char *mp, const char *dev)
  62. {
  63.     int res;
  64.     ipcarg_t rc;
  65.     aid_t req;
  66.  
  67.     int dev_handle = 0; /* TODO */
  68.  
  69.     futex_down(&vfs_phone_futex);
  70.     async_serialize_start();
  71.     if (vfs_phone < 0) {
  72.         res = vfs_connect();
  73.         if (res < 0) {
  74.             async_serialize_end();
  75.             futex_up(&vfs_phone_futex);
  76.             return res;
  77.         }
  78.     }
  79.     req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL);
  80.     rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name));
  81.     if (rc != EOK) {
  82.         async_wait_for(req, NULL);
  83.         async_serialize_end();
  84.         futex_up(&vfs_phone_futex);
  85.         return (int) rc;
  86.     }
  87.     rc = ipc_data_write_start(vfs_phone, (void *)mp, strlen(mp));
  88.     if (rc != EOK) {
  89.         async_wait_for(req, NULL);
  90.         async_serialize_end();
  91.         futex_up(&vfs_phone_futex);
  92.         return (int) rc;
  93.     }
  94.     async_wait_for(req, &rc);
  95.     async_serialize_end();
  96.     futex_up(&vfs_phone_futex);
  97.     return (int) rc;
  98. }
  99.  
  100. static int _open(const char *path, int lflag, int oflag, ...)
  101. {
  102.     int res;
  103.     ipcarg_t rc;
  104.     ipc_call_t answer;
  105.     aid_t req;
  106.    
  107.     futex_down(&vfs_phone_futex);
  108.     async_serialize_start();
  109.     if (vfs_phone < 0) {
  110.         res = vfs_connect();
  111.         if (res < 0) {
  112.             async_serialize_end();
  113.             futex_up(&vfs_phone_futex);
  114.             return res;
  115.         }
  116.     }
  117.     req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
  118.     rc = ipc_data_write_start(vfs_phone, path, strlen(path));
  119.     if (rc != EOK) {
  120.         async_wait_for(req, NULL);
  121.         async_serialize_end();
  122.         futex_up(&vfs_phone_futex);
  123.         return (int) rc;
  124.     }
  125.     async_wait_for(req, &rc);
  126.     async_serialize_end();
  127.     futex_up(&vfs_phone_futex);
  128.     return (int) IPC_GET_ARG1(answer);
  129. }
  130.  
  131. int open(const char *path, int oflag, ...)
  132. {
  133.     return _open(path, L_FILE, oflag);
  134. }
  135.  
  136. int close(int fildes)
  137. {
  138.     int res;
  139.     ipcarg_t rc;
  140.  
  141.     futex_down(&vfs_phone_futex);
  142.     async_serialize_start();
  143.     if (vfs_phone < 0) {
  144.         res = vfs_connect();
  145.         if (res < 0) {
  146.             async_serialize_end();
  147.             futex_up(&vfs_phone_futex);
  148.             return res;
  149.         }
  150.     }
  151.        
  152.     rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
  153.  
  154.     async_serialize_end();
  155.     futex_up(&vfs_phone_futex);
  156.    
  157.     return (int)rc;
  158. }
  159.  
  160. ssize_t read(int fildes, void *buf, size_t nbyte)
  161. {
  162.     int res;
  163.     ipcarg_t rc;
  164.     ipc_call_t answer;
  165.     aid_t req;
  166.  
  167.     futex_down(&vfs_phone_futex);
  168.     async_serialize_start();
  169.     if (vfs_phone < 0) {
  170.         res = vfs_connect();
  171.         if (res < 0) {
  172.             async_serialize_end();
  173.             futex_up(&vfs_phone_futex);
  174.             return res;
  175.         }
  176.     }
  177.     req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
  178.     rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
  179.     if (rc != EOK) {
  180.         async_wait_for(req, NULL);
  181.         async_serialize_end();
  182.         futex_up(&vfs_phone_futex);
  183.         return (ssize_t) rc;
  184.     }
  185.     async_wait_for(req, &rc);
  186.     async_serialize_end();
  187.     futex_up(&vfs_phone_futex);
  188.     if (rc == EOK)
  189.         return (ssize_t) IPC_GET_ARG1(answer);
  190.     else
  191.         return -1;
  192. }
  193.  
  194. ssize_t write(int fildes, const void *buf, size_t nbyte)
  195. {
  196.     int res;
  197.     ipcarg_t rc;
  198.     ipc_call_t answer;
  199.     aid_t req;
  200.  
  201.     futex_down(&vfs_phone_futex);
  202.     async_serialize_start();
  203.     if (vfs_phone < 0) {
  204.         res = vfs_connect();
  205.         if (res < 0) {
  206.             async_serialize_end();
  207.             futex_up(&vfs_phone_futex);
  208.             return res;
  209.         }
  210.     }
  211.     req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
  212.     rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
  213.     if (rc != EOK) {
  214.         async_wait_for(req, NULL);
  215.         async_serialize_end();
  216.         futex_up(&vfs_phone_futex);
  217.         return (ssize_t) rc;
  218.     }
  219.     async_wait_for(req, &rc);
  220.     async_serialize_end();
  221.     futex_up(&vfs_phone_futex);
  222.     if (rc == EOK)
  223.         return (ssize_t) IPC_GET_ARG1(answer);
  224.     else
  225.         return -1;
  226. }
  227.  
  228. off_t lseek(int fildes, off_t offset, int whence)
  229. {
  230.     int res;
  231.     ipcarg_t rc;
  232.  
  233.     futex_down(&vfs_phone_futex);
  234.     async_serialize_start();
  235.     if (vfs_phone < 0) {
  236.         res = vfs_connect();
  237.         if (res < 0) {
  238.             async_serialize_end();
  239.             futex_up(&vfs_phone_futex);
  240.             return res;
  241.         }
  242.     }
  243.        
  244.     off_t newoffs;
  245.     rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
  246.         (ipcarg_t)&newoffs);
  247.  
  248.     async_serialize_end();
  249.     futex_up(&vfs_phone_futex);
  250.  
  251.     if (rc != EOK)
  252.         return (off_t) -1;
  253.    
  254.     return newoffs;
  255. }
  256.  
  257. int ftruncate(int fildes, off_t length)
  258. {
  259.     int res;
  260.     ipcarg_t rc;
  261.    
  262.     futex_down(&vfs_phone_futex);
  263.     async_serialize_start();
  264.     if (vfs_phone < 0) {
  265.         res = vfs_connect();
  266.         if (res < 0) {
  267.             async_serialize_end();
  268.             futex_up(&vfs_phone_futex);
  269.             return res;
  270.         }
  271.     }
  272.     rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
  273.     async_serialize_end();
  274.     futex_up(&vfs_phone_futex);
  275.     return (int) rc;
  276. }
  277.  
  278. DIR *opendir(const char *dirname)
  279. {
  280.     DIR *dirp = malloc(sizeof(DIR));
  281.     if (!dirp)
  282.         return NULL;
  283.     dirp->fd = _open(dirname, L_DIRECTORY, 0);
  284.     if (dirp->fd < 0) {
  285.         free(dirp);
  286.         return NULL;
  287.     }
  288.     return dirp;
  289. }
  290.  
  291. struct dirent *readdir(DIR *dirp)
  292. {
  293.     ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
  294.     if (len <= 0)
  295.         return NULL;
  296.     return &dirp->res;
  297. }
  298.  
  299. void rewinddir(DIR *dirp)
  300. {
  301.     (void) lseek(dirp->fd, 0, SEEK_SET);
  302. }
  303.  
  304. int closedir(DIR *dirp)
  305. {
  306.     (void) close(dirp->fd);
  307.     free(dirp);
  308.     return 0;
  309. }
  310.  
  311. int mkdir(const char *path, mode_t mode)
  312. {
  313.     int res;
  314.     ipcarg_t rc;
  315.     aid_t req;
  316.    
  317.     futex_down(&vfs_phone_futex);
  318.     async_serialize_start();
  319.     if (vfs_phone < 0) {
  320.         res = vfs_connect();
  321.         if (res < 0) {
  322.             async_serialize_end();
  323.             futex_up(&vfs_phone_futex);
  324.             return res;
  325.         }
  326.     }
  327.     req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
  328.     rc = ipc_data_write_start(vfs_phone, path, strlen(path));
  329.     if (rc != EOK) {
  330.         async_wait_for(req, NULL);
  331.         async_serialize_end();
  332.         futex_up(&vfs_phone_futex);
  333.         return (int) rc;
  334.     }
  335.     async_wait_for(req, &rc);
  336.     async_serialize_end();
  337.     futex_up(&vfs_phone_futex);
  338.     return EOK;
  339. }
  340.  
  341. static int _unlink(const char *path, int lflag)
  342. {
  343.     int res;
  344.     ipcarg_t rc;
  345.     aid_t req;
  346.    
  347.     futex_down(&vfs_phone_futex);
  348.     async_serialize_start();
  349.     if (vfs_phone < 0) {
  350.         res = vfs_connect();
  351.         if (res < 0) {
  352.             async_serialize_end();
  353.             futex_up(&vfs_phone_futex);
  354.             return res;
  355.         }
  356.     }
  357.     req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
  358.     rc = ipc_data_write_start(vfs_phone, path, strlen(path));
  359.     if (rc != EOK) {
  360.         async_wait_for(req, NULL);
  361.         async_serialize_end();
  362.         futex_up(&vfs_phone_futex);
  363.         return (int) rc;
  364.     }
  365.     async_wait_for(req, &rc);
  366.     async_serialize_end();
  367.     futex_up(&vfs_phone_futex);
  368.     return EOK;
  369. }
  370.  
  371. int unlink(const char *path)
  372. {
  373.     return _unlink(path, L_NONE);
  374. }
  375.  
  376. int rmdir(const char *path)
  377. {
  378.     return _unlink(path, L_DIRECTORY);
  379. }
  380.  
  381. /** @}
  382.  */
  383.