fs.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* Copyright (C) 2014 Stony Brook University
  2. This file is part of Graphene Library OS.
  3. Graphene Library OS is free software: you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public License
  5. as published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. Graphene Library OS is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /*
  14. * fs.c
  15. *
  16. * This file contains codes for implementation of 'socket' filesystem.
  17. */
  18. #include <asm/fcntl.h>
  19. #include <asm/mman.h>
  20. #include <asm/prctl.h>
  21. #include <asm/unistd.h>
  22. #include <errno.h>
  23. #include <linux/fcntl.h>
  24. #include <pal.h>
  25. #include <pal_error.h>
  26. #include <shim_fs.h>
  27. #include <shim_internal.h>
  28. #include <shim_profile.h>
  29. // TODO: For some reason S_IF* macros are missing if this file is included before our headers. We
  30. // should investigate and fix this behavior.
  31. #include <linux/stat.h>
  32. static int socket_close(struct shim_handle* hdl) {
  33. /* XXX: Shouldn't this do something? */
  34. __UNUSED(hdl);
  35. return 0;
  36. }
  37. static ssize_t socket_read(struct shim_handle* hdl, void* buf, size_t count) {
  38. struct shim_sock_handle* sock = &hdl->info.sock;
  39. if (!count)
  40. return 0;
  41. lock(&hdl->lock);
  42. if (sock->sock_type == SOCK_STREAM && sock->sock_state != SOCK_ACCEPTED &&
  43. sock->sock_state != SOCK_CONNECTED && sock->sock_state != SOCK_BOUNDCONNECTED) {
  44. sock->error = ENOTCONN;
  45. unlock(&hdl->lock);
  46. return -ENOTCONN;
  47. }
  48. if (sock->sock_type == SOCK_DGRAM && sock->sock_state != SOCK_CONNECTED &&
  49. sock->sock_state != SOCK_BOUNDCONNECTED) {
  50. sock->error = EDESTADDRREQ;
  51. unlock(&hdl->lock);
  52. return -EDESTADDRREQ;
  53. }
  54. unlock(&hdl->lock);
  55. PAL_NUM bytes = DkStreamRead(hdl->pal_handle, 0, count, buf, NULL, 0);
  56. if (!bytes)
  57. switch (PAL_NATIVE_ERRNO) {
  58. case PAL_ERROR_ENDOFSTREAM:
  59. return 0;
  60. default: {
  61. int err = PAL_ERRNO;
  62. lock(&hdl->lock);
  63. sock->error = err;
  64. unlock(&hdl->lock);
  65. return -err;
  66. }
  67. }
  68. assert((ssize_t)bytes > 0);
  69. return (ssize_t)bytes;
  70. }
  71. static ssize_t socket_write(struct shim_handle* hdl, const void* buf, size_t count) {
  72. struct shim_sock_handle* sock = &hdl->info.sock;
  73. lock(&hdl->lock);
  74. if (sock->sock_type == SOCK_STREAM && sock->sock_state != SOCK_ACCEPTED &&
  75. sock->sock_state != SOCK_CONNECTED && sock->sock_state != SOCK_BOUNDCONNECTED) {
  76. sock->error = ENOTCONN;
  77. unlock(&hdl->lock);
  78. return -ENOTCONN;
  79. }
  80. if (sock->sock_type == SOCK_DGRAM && sock->sock_state != SOCK_CONNECTED &&
  81. sock->sock_state != SOCK_BOUNDCONNECTED) {
  82. sock->error = EDESTADDRREQ;
  83. unlock(&hdl->lock);
  84. return -EDESTADDRREQ;
  85. }
  86. unlock(&hdl->lock);
  87. if (!count)
  88. return 0;
  89. PAL_NUM bytes = DkStreamWrite(hdl->pal_handle, 0, count, (void*)buf, NULL);
  90. if (!bytes) {
  91. int err;
  92. switch (PAL_NATIVE_ERRNO) {
  93. case PAL_ERROR_CONNFAILED:
  94. err = EPIPE;
  95. break;
  96. default:
  97. err = PAL_ERRNO;
  98. break;
  99. }
  100. lock(&hdl->lock);
  101. sock->error = err;
  102. unlock(&hdl->lock);
  103. return -err;
  104. }
  105. assert((ssize_t)bytes > 0);
  106. return (ssize_t)bytes;
  107. }
  108. static int socket_hstat(struct shim_handle* hdl, struct stat* stat) {
  109. if (!stat)
  110. return 0;
  111. PAL_STREAM_ATTR attr;
  112. if (!DkStreamAttributesQueryByHandle(hdl->pal_handle, &attr))
  113. return -PAL_ERRNO;
  114. memset(stat, 0, sizeof(struct stat));
  115. stat->st_ino = 0;
  116. stat->st_size = (off_t)attr.pending_size;
  117. stat->st_mode = S_IFSOCK;
  118. return 0;
  119. }
  120. static int socket_checkout(struct shim_handle* hdl) {
  121. hdl->fs = NULL;
  122. return 0;
  123. }
  124. static off_t socket_poll(struct shim_handle* hdl, int poll_type) {
  125. struct shim_sock_handle* sock = &hdl->info.sock;
  126. off_t ret = 0;
  127. lock(&hdl->lock);
  128. if (poll_type & FS_POLL_RD) {
  129. if (sock->sock_type == SOCK_STREAM) {
  130. if (sock->sock_state == SOCK_CREATED || sock->sock_state == SOCK_BOUND ||
  131. sock->sock_state == SOCK_SHUTDOWN) {
  132. ret = -ENOTCONN;
  133. goto out;
  134. }
  135. }
  136. if (sock->sock_type == SOCK_DGRAM && sock->sock_state == SOCK_SHUTDOWN) {
  137. ret = -ENOTCONN;
  138. goto out;
  139. }
  140. }
  141. if (poll_type & FS_POLL_WR) {
  142. if (sock->sock_type == SOCK_STREAM) {
  143. if (sock->sock_state == SOCK_CREATED || sock->sock_state == SOCK_BOUND ||
  144. sock->sock_state == SOCK_LISTENED || sock->sock_state == SOCK_SHUTDOWN) {
  145. ret = -ENOTCONN;
  146. goto out;
  147. }
  148. }
  149. if (sock->sock_type == SOCK_DGRAM && sock->sock_state == SOCK_SHUTDOWN) {
  150. ret = -ENOTCONN;
  151. goto out;
  152. }
  153. }
  154. if (!hdl->pal_handle) {
  155. ret = -EBADF;
  156. goto out;
  157. }
  158. PAL_STREAM_ATTR attr;
  159. if (!DkStreamAttributesQueryByHandle(hdl->pal_handle, &attr)) {
  160. ret = -PAL_ERRNO;
  161. goto out;
  162. }
  163. if (poll_type == FS_POLL_SZ) {
  164. ret = attr.pending_size;
  165. goto out;
  166. }
  167. ret = 0;
  168. if (attr.disconnected)
  169. ret |= FS_POLL_ER;
  170. if ((poll_type & FS_POLL_RD) && attr.readable)
  171. ret |= FS_POLL_RD;
  172. if ((poll_type & FS_POLL_WR) && attr.writable)
  173. ret |= FS_POLL_WR;
  174. out:
  175. if (ret < 0) {
  176. debug("socket_poll failed (%ld)\n", ret);
  177. sock->error = -ret;
  178. }
  179. unlock(&hdl->lock);
  180. return ret;
  181. }
  182. static int socket_setflags(struct shim_handle* hdl, int flags) {
  183. if (!hdl->pal_handle)
  184. return 0;
  185. PAL_STREAM_ATTR attr;
  186. if (!DkStreamAttributesQueryByHandle(hdl->pal_handle, &attr))
  187. return -PAL_ERRNO;
  188. if (attr.nonblocking) {
  189. if (flags & O_NONBLOCK)
  190. return 0;
  191. attr.nonblocking = PAL_FALSE;
  192. } else {
  193. if (!(flags & O_NONBLOCK))
  194. return 0;
  195. attr.nonblocking = PAL_TRUE;
  196. }
  197. if (!DkStreamAttributesSetByHandle(hdl->pal_handle, &attr))
  198. return -PAL_ERRNO;
  199. return 0;
  200. }
  201. struct shim_fs_ops socket_fs_ops = {
  202. .close = &socket_close,
  203. .read = &socket_read,
  204. .write = &socket_write,
  205. .hstat = &socket_hstat,
  206. .checkout = &socket_checkout,
  207. .poll = &socket_poll,
  208. .setflags = &socket_setflags,
  209. };
  210. struct shim_mount socket_builtin_fs = {
  211. .type = "socket",
  212. .fs_ops = &socket_fs_ops,
  213. };