Subversion Repositories HelenOS

Rev

Rev 2771 | Rev 3150 | 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/vfs.h>
  36. #include <vfs/canonify.h>
  37. #include <stdlib.h>
  38. #include <unistd.h>
  39. #include <dirent.h>
  40. #include <fcntl.h>
  41. #include <sys/stat.h>
  42. #include <stdio.h>
  43. #include <sys/types.h>
  44. #include <ipc/ipc.h>
  45. #include <ipc/services.h>
  46. #include <async.h>
  47. #include <atomic.h>
  48. #include <futex.h>
  49. #include <errno.h>
  50. #include <string.h>
  51. #include "../../srv/vfs/vfs.h"
  52.  
  53. int vfs_phone = -1;
  54. futex_t vfs_phone_futex = FUTEX_INITIALIZER;
  55.  
  56. futex_t cwd_futex = FUTEX_INITIALIZER;
  57. DIR *cwd_dir = NULL;
  58. char *cwd_path = NULL;
  59. size_t cwd_len = 0;
  60.  
  61. static char *absolutize(const char *path, size_t *retlen)
  62. {
  63.     char *ncwd_path;
  64.  
  65.     futex_down(&cwd_futex);
  66.     size_t len = strlen(path);
  67.     if (*path != '/') {
  68.         if (!cwd_path) {
  69.             futex_up(&cwd_futex);
  70.             return NULL;
  71.         }
  72.         ncwd_path = malloc(len + cwd_len + 1);
  73.         if (!ncwd_path) {
  74.             futex_up(&cwd_futex);
  75.             return NULL;
  76.         }
  77.         strcpy(ncwd_path, cwd_path);
  78.         ncwd_path[cwd_len] = '/';
  79.         ncwd_path[cwd_len + 1] = '\0';
  80.     } else {
  81.         ncwd_path = malloc(len + 1);
  82.         if (!ncwd_path) {
  83.             futex_up(&cwd_futex);
  84.             return NULL;
  85.         }
  86.         ncwd_path[0] = '\0';
  87.     }
  88.     strcat(ncwd_path, path);
  89.     if (!canonify(ncwd_path, retlen)) {
  90.         futex_up(&cwd_futex);
  91.         free(ncwd_path);
  92.         return NULL;
  93.     }
  94.     futex_up(&cwd_futex);
  95.     return ncwd_path;
  96. }
  97.  
  98. static int vfs_connect(void)
  99. {
  100.     if (vfs_phone < 0)
  101.         vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
  102.     return vfs_phone;
  103. }
  104.  
  105. int mount(const char *fs_name, const char *mp, const char *dev)
  106. {
  107.     int res;
  108.     ipcarg_t rc;
  109.     aid_t req;
  110.  
  111.     dev_handle_t dev_handle = 0;    /* TODO */
  112.  
  113.     size_t mpa_len;
  114.     char *mpa = absolutize(mp, &mpa_len);
  115.     if (!mpa)
  116.         return ENOMEM;
  117.  
  118.     futex_down(&vfs_phone_futex);
  119.     async_serialize_start();
  120.     if (vfs_phone < 0) {
  121.         res = vfs_connect();
  122.         if (res < 0) {
  123.             async_serialize_end();
  124.             futex_up(&vfs_phone_futex);
  125.             free(mpa);
  126.             return res;
  127.         }
  128.     }
  129.     req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL);
  130.     rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name));
  131.     if (rc != EOK) {
  132.         async_wait_for(req, NULL);
  133.         async_serialize_end();
  134.         futex_up(&vfs_phone_futex);
  135.         free(mpa);
  136.         return (int) rc;
  137.     }
  138.     rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
  139.     if (rc != EOK) {
  140.         async_wait_for(req, NULL);
  141.         async_serialize_end();
  142.         futex_up(&vfs_phone_futex);
  143.         free(mpa);
  144.         return (int) rc;
  145.     }
  146.     async_wait_for(req, &rc);
  147.     async_serialize_end();
  148.     futex_up(&vfs_phone_futex);
  149.     free(mpa);
  150.     return (int) rc;
  151. }
  152.  
  153. static int _open(const char *path, int lflag, int oflag, ...)
  154. {
  155.     int res;
  156.     ipcarg_t rc;
  157.     ipc_call_t answer;
  158.     aid_t req;
  159.    
  160.     size_t pa_len;
  161.     char *pa = absolutize(path, &pa_len);
  162.     if (!pa)
  163.         return ENOMEM;
  164.    
  165.     futex_down(&vfs_phone_futex);
  166.     async_serialize_start();
  167.     if (vfs_phone < 0) {
  168.         res = vfs_connect();
  169.         if (res < 0) {
  170.             async_serialize_end();
  171.             futex_up(&vfs_phone_futex);
  172.             free(pa);
  173.             return res;
  174.         }
  175.     }
  176.     req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
  177.     rc = ipc_data_write_start(vfs_phone, pa, pa_len);
  178.     if (rc != EOK) {
  179.         async_wait_for(req, NULL);
  180.         async_serialize_end();
  181.         futex_up(&vfs_phone_futex);
  182.         free(pa);
  183.         return (int) rc;
  184.     }
  185.     async_wait_for(req, &rc);
  186.     async_serialize_end();
  187.     futex_up(&vfs_phone_futex);
  188.     free(pa);
  189.     return (int) IPC_GET_ARG1(answer);
  190. }
  191.  
  192. int open(const char *path, int oflag, ...)
  193. {
  194.     return _open(path, L_FILE, oflag);
  195. }
  196.  
  197. int close(int fildes)
  198. {
  199.     int res;
  200.     ipcarg_t rc;
  201.  
  202.     futex_down(&vfs_phone_futex);
  203.     async_serialize_start();
  204.     if (vfs_phone < 0) {
  205.         res = vfs_connect();
  206.         if (res < 0) {
  207.             async_serialize_end();
  208.             futex_up(&vfs_phone_futex);
  209.             return res;
  210.         }
  211.     }
  212.        
  213.     rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
  214.  
  215.     async_serialize_end();
  216.     futex_up(&vfs_phone_futex);
  217.    
  218.     return (int)rc;
  219. }
  220.  
  221. ssize_t read(int fildes, void *buf, size_t nbyte)
  222. {
  223.     int res;
  224.     ipcarg_t rc;
  225.     ipc_call_t answer;
  226.     aid_t req;
  227.  
  228.     futex_down(&vfs_phone_futex);
  229.     async_serialize_start();
  230.     if (vfs_phone < 0) {
  231.         res = vfs_connect();
  232.         if (res < 0) {
  233.             async_serialize_end();
  234.             futex_up(&vfs_phone_futex);
  235.             return res;
  236.         }
  237.     }
  238.     req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
  239.     rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
  240.     if (rc != EOK) {
  241.         async_wait_for(req, NULL);
  242.         async_serialize_end();
  243.         futex_up(&vfs_phone_futex);
  244.         return (ssize_t) rc;
  245.     }
  246.     async_wait_for(req, &rc);
  247.     async_serialize_end();
  248.     futex_up(&vfs_phone_futex);
  249.     if (rc == EOK)
  250.         return (ssize_t) IPC_GET_ARG1(answer);
  251.     else
  252.         return -1;
  253. }
  254.  
  255. ssize_t write(int fildes, const void *buf, size_t nbyte)
  256. {
  257.     int res;
  258.     ipcarg_t rc;
  259.     ipc_call_t answer;
  260.     aid_t req;
  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.     req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
  273.     rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
  274.     if (rc != EOK) {
  275.         async_wait_for(req, NULL);
  276.         async_serialize_end();
  277.         futex_up(&vfs_phone_futex);
  278.         return (ssize_t) rc;
  279.     }
  280.     async_wait_for(req, &rc);
  281.     async_serialize_end();
  282.     futex_up(&vfs_phone_futex);
  283.     if (rc == EOK)
  284.         return (ssize_t) IPC_GET_ARG1(answer);
  285.     else
  286.         return -1;
  287. }
  288.  
  289. off_t lseek(int fildes, off_t offset, int whence)
  290. {
  291.     int res;
  292.     ipcarg_t rc;
  293.  
  294.     futex_down(&vfs_phone_futex);
  295.     async_serialize_start();
  296.     if (vfs_phone < 0) {
  297.         res = vfs_connect();
  298.         if (res < 0) {
  299.             async_serialize_end();
  300.             futex_up(&vfs_phone_futex);
  301.             return res;
  302.         }
  303.     }
  304.        
  305.     off_t newoffs;
  306.     rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
  307.         (ipcarg_t)&newoffs);
  308.  
  309.     async_serialize_end();
  310.     futex_up(&vfs_phone_futex);
  311.  
  312.     if (rc != EOK)
  313.         return (off_t) -1;
  314.    
  315.     return newoffs;
  316. }
  317.  
  318. int ftruncate(int fildes, off_t length)
  319. {
  320.     int res;
  321.     ipcarg_t rc;
  322.    
  323.     futex_down(&vfs_phone_futex);
  324.     async_serialize_start();
  325.     if (vfs_phone < 0) {
  326.         res = vfs_connect();
  327.         if (res < 0) {
  328.             async_serialize_end();
  329.             futex_up(&vfs_phone_futex);
  330.             return res;
  331.         }
  332.     }
  333.     rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
  334.     async_serialize_end();
  335.     futex_up(&vfs_phone_futex);
  336.     return (int) rc;
  337. }
  338.  
  339. DIR *opendir(const char *dirname)
  340. {
  341.     DIR *dirp = malloc(sizeof(DIR));
  342.     if (!dirp)
  343.         return NULL;
  344.     dirp->fd = _open(dirname, L_DIRECTORY, 0);
  345.     if (dirp->fd < 0) {
  346.         free(dirp);
  347.         return NULL;
  348.     }
  349.     return dirp;
  350. }
  351.  
  352. struct dirent *readdir(DIR *dirp)
  353. {
  354.     ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
  355.     if (len <= 0)
  356.         return NULL;
  357.     return &dirp->res;
  358. }
  359.  
  360. void rewinddir(DIR *dirp)
  361. {
  362.     (void) lseek(dirp->fd, 0, SEEK_SET);
  363. }
  364.  
  365. int closedir(DIR *dirp)
  366. {
  367.     (void) close(dirp->fd);
  368.     free(dirp);
  369.     return 0;
  370. }
  371.  
  372. int mkdir(const char *path, mode_t mode)
  373. {
  374.     int res;
  375.     ipcarg_t rc;
  376.     aid_t req;
  377.    
  378.     size_t pa_len;
  379.     char *pa = absolutize(path, &pa_len);
  380.     if (!pa)
  381.         return ENOMEM;
  382.  
  383.     futex_down(&vfs_phone_futex);
  384.     async_serialize_start();
  385.     if (vfs_phone < 0) {
  386.         res = vfs_connect();
  387.         if (res < 0) {
  388.             async_serialize_end();
  389.             futex_up(&vfs_phone_futex);
  390.             free(pa);
  391.             return res;
  392.         }
  393.     }
  394.     req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
  395.     rc = ipc_data_write_start(vfs_phone, pa, pa_len);
  396.     if (rc != EOK) {
  397.         async_wait_for(req, NULL);
  398.         async_serialize_end();
  399.         futex_up(&vfs_phone_futex);
  400.         free(pa);
  401.         return (int) rc;
  402.     }
  403.     async_wait_for(req, &rc);
  404.     async_serialize_end();
  405.     futex_up(&vfs_phone_futex);
  406.     free(pa);
  407.     return rc;
  408. }
  409.  
  410. static int _unlink(const char *path, int lflag)
  411. {
  412.     int res;
  413.     ipcarg_t rc;
  414.     aid_t req;
  415.    
  416.     size_t pa_len;
  417.     char *pa = absolutize(path, &pa_len);
  418.     if (!pa)
  419.         return ENOMEM;
  420.  
  421.     futex_down(&vfs_phone_futex);
  422.     async_serialize_start();
  423.     if (vfs_phone < 0) {
  424.         res = vfs_connect();
  425.         if (res < 0) {
  426.             async_serialize_end();
  427.             futex_up(&vfs_phone_futex);
  428.             free(pa);
  429.             return res;
  430.         }
  431.     }
  432.     req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
  433.     rc = ipc_data_write_start(vfs_phone, pa, pa_len);
  434.     if (rc != EOK) {
  435.         async_wait_for(req, NULL);
  436.         async_serialize_end();
  437.         futex_up(&vfs_phone_futex);
  438.         free(pa);
  439.         return (int) rc;
  440.     }
  441.     async_wait_for(req, &rc);
  442.     async_serialize_end();
  443.     futex_up(&vfs_phone_futex);
  444.     free(pa);
  445.     return rc;
  446. }
  447.  
  448. int unlink(const char *path)
  449. {
  450.     return _unlink(path, L_NONE);
  451. }
  452.  
  453. int rmdir(const char *path)
  454. {
  455.     return _unlink(path, L_DIRECTORY);
  456. }
  457.  
  458. int rename(const char *old, const char *new)
  459. {
  460.     int res;
  461.     ipcarg_t rc;
  462.     aid_t req;
  463.    
  464.     size_t olda_len;
  465.     char *olda = absolutize(old, &olda_len);
  466.     if (!olda)
  467.         return ENOMEM;
  468.  
  469.     size_t newa_len;
  470.     char *newa = absolutize(new, &newa_len);
  471.     if (!newa) {
  472.         free(olda);
  473.         return ENOMEM;
  474.     }
  475.  
  476.     futex_down(&vfs_phone_futex);
  477.     async_serialize_start();
  478.     if (vfs_phone < 0) {
  479.         res = vfs_connect();
  480.         if (res < 0) {
  481.             async_serialize_end();
  482.             futex_up(&vfs_phone_futex);
  483.             free(olda);
  484.             free(newa);
  485.             return res;
  486.         }
  487.     }
  488.     req = async_send_0(vfs_phone, VFS_RENAME, NULL);
  489.     rc = ipc_data_write_start(vfs_phone, olda, olda_len);
  490.     if (rc != EOK) {
  491.         async_wait_for(req, NULL);
  492.         async_serialize_end();
  493.         futex_up(&vfs_phone_futex);
  494.         free(olda);
  495.         free(newa);
  496.         return (int) rc;
  497.     }
  498.     rc = ipc_data_write_start(vfs_phone, newa, newa_len);
  499.     if (rc != EOK) {
  500.         async_wait_for(req, NULL);
  501.         async_serialize_end();
  502.         futex_up(&vfs_phone_futex);
  503.         free(olda);
  504.         free(newa);
  505.         return (int) rc;
  506.     }
  507.     async_wait_for(req, &rc);
  508.     async_serialize_end();
  509.     futex_up(&vfs_phone_futex);
  510.     free(olda);
  511.     free(newa);
  512.     return rc;
  513. }
  514.  
  515. int chdir(const char *path)
  516. {
  517.     size_t pa_len;
  518.     char *pa = absolutize(path, &pa_len);
  519.     if (!pa)
  520.         return ENOMEM;
  521.  
  522.     DIR *d = opendir(pa);
  523.     if (!d) {
  524.         free(pa);
  525.         return ENOENT;
  526.     }
  527.  
  528.     futex_down(&cwd_futex);
  529.     if (cwd_dir) {
  530.         closedir(cwd_dir);
  531.         cwd_dir = NULL;
  532.         free(cwd_path);
  533.         cwd_path = NULL;
  534.         cwd_len = 0;
  535.     }
  536.     cwd_dir = d;
  537.     cwd_path = pa;
  538.     cwd_len = pa_len;
  539.     futex_up(&cwd_futex);
  540. }
  541.  
  542. char *getcwd(char *buf, size_t size)
  543. {
  544.     if (!size)
  545.         return NULL;
  546.     futex_down(&cwd_futex);
  547.     if (size < cwd_len + 1) {
  548.         futex_up(&cwd_futex);
  549.         return NULL;
  550.     }
  551.     strcpy(buf, cwd_path);
  552.     futex_up(&cwd_futex);
  553.     return buf;
  554. }
  555.  
  556. /** @}
  557.  */
  558.