fs.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * fs.c
  17. *
  18. * This file contains codes for implementation of 'str' filesystem.
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_fs.h>
  22. #include <shim_profile.h>
  23. #include <pal.h>
  24. #include <pal_error.h>
  25. #include <asm/mman.h>
  26. #include <asm/unistd.h>
  27. #include <asm/prctl.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. int str_open (struct shim_handle * hdl, struct shim_dentry * dent,
  31. int flags)
  32. {
  33. struct shim_str_data * data = dent->data;
  34. /* when str file is opened, it must have a data */
  35. if (!dent->data)
  36. return -ENOENT;
  37. REF_INC(data->ref_count);
  38. hdl->dentry = dent;
  39. hdl->flags = flags;
  40. return 0;
  41. }
  42. int str_dput (struct shim_dentry * dent)
  43. {
  44. struct shim_str_data * data = dent->data;
  45. if (!data || REF_DEC(data->ref_count) > 1)
  46. return 0;
  47. if (data->str) {
  48. free(data->str);
  49. data->str = NULL;
  50. }
  51. data->len = 0;
  52. data->buf_size = 0;
  53. free(dent->data);
  54. dent->data = NULL;
  55. return 0;
  56. }
  57. int str_close (struct shim_handle * hdl)
  58. {
  59. if (hdl->flags && (O_WRONLY|O_RDWR)) {
  60. int ret = str_flush(hdl);
  61. if (ret < 0)
  62. return ret;
  63. }
  64. str_dput(hdl->dentry);
  65. return 0;
  66. }
  67. int str_read (struct shim_handle * hdl, void * buf,
  68. size_t count)
  69. {
  70. int ret = 0;
  71. if (!(hdl->acc_mode && MAY_READ)) {
  72. ret = -EACCES;
  73. goto out;
  74. }
  75. struct shim_str_handle * strhdl = &hdl->info.str;
  76. assert(hdl->dentry);
  77. assert(strhdl->data);
  78. struct shim_str_data * data = strhdl->data;
  79. if (!data->str) {
  80. debug("str_data has no str\n");
  81. ret = -EACCES;
  82. goto out;
  83. }
  84. if (!strhdl->ptr)
  85. strhdl->ptr = data->str;
  86. int offset = strhdl->ptr - data->str;
  87. int remain = data->len - offset;
  88. if (count >= remain) {
  89. memcpy(buf, strhdl->ptr, remain);
  90. strhdl->ptr += remain;
  91. ret = remain;
  92. goto out;
  93. }
  94. memcpy(buf, strhdl->ptr, count);
  95. strhdl->ptr += count;
  96. ret = count;
  97. out:
  98. return ret;
  99. }
  100. int str_write (struct shim_handle * hdl, const void * buf,
  101. size_t count)
  102. {
  103. if (!(hdl->acc_mode && MAY_WRITE))
  104. return -EACCES;
  105. struct shim_str_handle * strhdl = &hdl->info.str;
  106. assert(hdl->dentry);
  107. assert(strhdl->data);
  108. struct shim_str_data * data = strhdl->data;
  109. if (!data->str ||
  110. strhdl->ptr + count > data->str + data->buf_size) {
  111. int newlen = 0;
  112. if (data->str) {
  113. newlen = data->buf_size * 2;
  114. while (strhdl->ptr + count > data->str + newlen)
  115. newlen *= 2;
  116. } else {
  117. newlen = count;
  118. }
  119. char * newbuf = malloc(newlen);
  120. if (!newbuf)
  121. return -ENOMEM;
  122. if (data->str) {
  123. memcpy(newbuf, data->str, data->len);
  124. free(data->str);
  125. }
  126. strhdl->ptr = newbuf + (strhdl->ptr - data->str);
  127. data->str = newbuf;
  128. data->buf_size = newlen;
  129. }
  130. memcpy(strhdl->ptr, buf, count);
  131. strhdl->ptr += count;
  132. data->dirty = true;
  133. if (strhdl->ptr >= data->str + data->len)
  134. data->len = strhdl->ptr - data->str;
  135. return count;
  136. }
  137. int str_seek (struct shim_handle * hdl, off_t offset,
  138. int whence)
  139. {
  140. struct shim_str_handle * strhdl = &hdl->info.str;
  141. assert(hdl->dentry);
  142. assert(strhdl->data);
  143. struct shim_str_data * data = strhdl->data;
  144. switch(whence) {
  145. case SEEK_SET:
  146. if (offset < 0)
  147. return -EINVAL;
  148. strhdl->ptr = data->str;
  149. if (strhdl->ptr > data->str + data->len)
  150. strhdl->ptr = data->str + data->len;
  151. break;
  152. case SEEK_CUR:
  153. if (offset >= 0) {
  154. strhdl->ptr += offset;
  155. if (strhdl->ptr > data->str + data->len)
  156. strhdl->ptr = data->str + data->len;
  157. } else {
  158. strhdl->ptr -= offset;
  159. if (strhdl->ptr < data->str)
  160. strhdl->ptr = data->str;
  161. }
  162. break;
  163. case SEEK_END:
  164. if (offset < 0)
  165. return -EINVAL;
  166. strhdl->ptr = data->str + data->len - offset;
  167. if (strhdl->ptr < data->str)
  168. strhdl->ptr = data->str;
  169. break;
  170. }
  171. return strhdl->ptr - data->str;
  172. }
  173. int str_flush (struct shim_handle * hdl)
  174. {
  175. struct shim_str_handle * strhdl = &hdl->info.str;
  176. assert(hdl->dentry);
  177. assert(strhdl->data);
  178. struct shim_str_data * data = strhdl->data;
  179. if (!data->dirty)
  180. return 0;
  181. if (!data->modify)
  182. return -EACCES;
  183. return data->modify(hdl);
  184. }
  185. struct shim_fs_ops str_fs_ops = {
  186. .close = &str_close,
  187. .read = &str_read,
  188. .write = &str_write,
  189. .seek = &str_seek,
  190. .flush = &str_flush,
  191. };
  192. struct shim_d_ops str_d_ops = {
  193. .open = &str_open,
  194. .dput = &str_dput,
  195. };