sgx_file.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "platform_api_vmcore.h"
  6. #include "sgx_error.h"
  7. #include "sgx_file.h"
  8. #ifndef SGX_DISABLE_WASI
  9. #define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__)
  10. #define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
  11. /** fd **/
  12. int ocall_open(int *p_fd, const char *pathname, int flags,
  13. bool has_mode, unsigned mode);
  14. int ocall_openat(int *p_fd, int dirfd, const char *pathname, int flags,
  15. bool has_mode, unsigned mode);
  16. int ocall_read(ssize_t *p_ret, int fd, void *buf, size_t read_size);
  17. int ocall_close(int *p_ret, int fd);
  18. int ocall_lseek(off_t *p_ret, int fd, off_t offset, int whence);
  19. int ocall_ftruncate(int *p_ret, int fd, off_t length);
  20. int ocall_fsync(int *p_ret, int fd);
  21. int ocall_fdatasync(int *p_ret, int fd);
  22. int ocall_isatty(int *p_ret, int fd);
  23. /** fd end **/
  24. /** DIR **/
  25. int ocall_fdopendir(int fd, void **p_dirp);
  26. int ocall_readdir(void **p_dirent, void *dirp);
  27. int ocall_rewinddir(void *dirp);
  28. int ocall_seekdir(void *dirp, long loc);
  29. int ocall_telldir(long *p_dir, void *dirp);
  30. int ocall_closedir(int *p_ret, void *dirp);
  31. /** DIR end **/
  32. /** stat **/
  33. int ocall_fstat(int *p_ret, int fd, void *buf, unsigned int buf_len);
  34. int ocall_fstatat(int *p_ret, int dirfd, const char *pathname, void *buf,
  35. unsigned int buf_len, int flags);
  36. /** stat end **/
  37. /** link **/
  38. int ocall_mkdirat(int *p_ret, int dirfd, const char * pathname,
  39. unsigned mode);
  40. int ocall_link(int *p_ret, const char *oldpath, const char *newpath);
  41. int ocall_linkat(int *p_ret, int olddirfd, const char *oldpath,
  42. int newdirfd, const char *newpath, int flags);
  43. int ocall_unlinkat(int *p_ret, int dirfd, const char *pathname,
  44. int flags);
  45. int ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname,
  46. char *buf, size_t bufsiz);
  47. int ocall_renameat(int *p_ret, int olddirfd,const char *oldpath,
  48. int newdirfd,const char *newpath);
  49. int ocall_symlinkat(int *p_ret, const char *target, int newdirfd,
  50. const char *linkpath);
  51. /** link end **/
  52. /** control **/
  53. int ocall_ioctl(int *p_ret, int fd, unsigned long request, void *arg,
  54. unsigned int arg_len);
  55. int ocall_fcntl(int *p_ret, int fd, int cmd);
  56. int ocall_fcntl_long(int *p_ret, int fd, int cmd, long arg);
  57. /** control end **/
  58. /** **/
  59. int ocall_realpath(int *p_ret, const char *path, char *buf,
  60. unsigned int buf_len);
  61. int ocall_posix_fallocate(int *p_ret, int fd, off_t offset, off_t len);
  62. int ocall_poll(int *p_ret, void *fds, unsigned nfds, int timeout,
  63. unsigned int fds_len);
  64. int ocall_getopt(int *p_ret, int argc, char *argv_buf,
  65. unsigned int argv_buf_len, const char *optstring);
  66. int ocall_getrandom(ssize_t *p_ret, void *buf, size_t buflen,
  67. unsigned int flags);
  68. int ocall_sched_yield(int *p_ret);
  69. /** struct iovec **/
  70. ssize_t ocall_readv(ssize_t *p_ret, int fd, char *iov_buf,
  71. unsigned int buf_size, int iovcnt,
  72. bool has_offset, off_t offset);
  73. ssize_t ocall_writev(ssize_t *p_ret, int fd, char *iov_buf,
  74. unsigned int buf_size, int iovcnt,
  75. bool has_offset, off_t offset);
  76. /** iovec end **/
  77. int ocall_get_errno(int *p_ret);
  78. int open(const char *pathname, int flags, ...)
  79. {
  80. int fd;
  81. bool has_mode = false;
  82. mode_t mode = 0;
  83. if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
  84. va_list ap;
  85. va_start(ap, flags);
  86. mode = va_arg(ap, mode_t);
  87. va_end(ap);
  88. has_mode = true;
  89. }
  90. if (SGX_SUCCESS != ocall_open(&fd, pathname, flags, has_mode, mode)) {
  91. TRACE_OCALL_FAIL();
  92. return -1;
  93. }
  94. if (fd >= 0 && (flags & O_CLOEXEC))
  95. fcntl(fd, F_SETFD, FD_CLOEXEC);
  96. if (fd == -1)
  97. errno = get_errno();
  98. return fd;
  99. }
  100. int openat(int dirfd, const char *pathname, int flags, ...)
  101. {
  102. int fd;
  103. bool has_mode = false;
  104. mode_t mode = 0;
  105. if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
  106. va_list ap;
  107. va_start(ap, flags);
  108. mode = va_arg(ap, mode_t);
  109. va_end(ap);
  110. has_mode = true;
  111. }
  112. if (SGX_SUCCESS != ocall_openat(&fd, dirfd, pathname, flags,
  113. has_mode, mode)) {
  114. TRACE_OCALL_FAIL();
  115. return -1;
  116. }
  117. if (fd >= 0 && (flags & O_CLOEXEC))
  118. fcntl(fd, F_SETFD, FD_CLOEXEC);
  119. if (fd == -1)
  120. errno = get_errno();
  121. return fd;
  122. }
  123. int close(int fd)
  124. {
  125. int ret;
  126. if (ocall_close(&ret, fd) != SGX_SUCCESS) {
  127. TRACE_OCALL_FAIL();
  128. return -1;
  129. }
  130. if (ret == -1)
  131. errno = get_errno();
  132. return ret;
  133. }
  134. ssize_t read(int fd, void *buf, size_t size)
  135. {
  136. ssize_t ret;
  137. int size_read_max = 2048, size_read, total_size_read = 0, count, i;
  138. char *p = buf;
  139. if (buf == NULL) {
  140. TRACE_FUNC();
  141. return -1;
  142. }
  143. count = (size + size_read_max - 1) / size_read_max;
  144. for (i = 0; i < count; i++) {
  145. size_read = (i < count - 1)
  146. ? size_read_max
  147. : size - size_read_max * i;
  148. if (ocall_read(&ret, fd, p, size_read) != SGX_SUCCESS) {
  149. TRACE_OCALL_FAIL();
  150. return -1;
  151. }
  152. if (ret == -1) {
  153. /* read failed */
  154. errno = get_errno();
  155. return -1;
  156. }
  157. p += ret;
  158. total_size_read += ret;
  159. if (ret < size_read)
  160. /* end of file */
  161. break;
  162. }
  163. return total_size_read;
  164. }
  165. DIR *fdopendir(int fd)
  166. {
  167. DIR *result = NULL;
  168. result = (DIR *)BH_MALLOC(sizeof(DIR));
  169. if (!result)
  170. return NULL;
  171. if (ocall_fdopendir(fd, (void **)result) != SGX_SUCCESS) {
  172. TRACE_OCALL_FAIL();
  173. BH_FREE(result);
  174. return NULL;
  175. }
  176. if ((void *)*result == NULL) { /* opendir failed */
  177. TRACE_FUNC();
  178. BH_FREE(result);
  179. errno = get_errno();
  180. return NULL;
  181. }
  182. return result;
  183. }
  184. struct dirent *readdir(DIR *dirp)
  185. {
  186. struct dirent *result;
  187. if (dirp == NULL)
  188. return NULL;
  189. if (ocall_readdir((void **)&result, (void *)*dirp) != SGX_SUCCESS) {
  190. TRACE_OCALL_FAIL();
  191. return NULL;
  192. }
  193. if (!result)
  194. errno = get_errno();
  195. return result;
  196. }
  197. void rewinddir(DIR *dirp)
  198. {
  199. if (ocall_rewinddir((void *)*dirp) != SGX_SUCCESS) {
  200. TRACE_OCALL_FAIL();
  201. }
  202. }
  203. void seekdir(DIR *dirp, long loc)
  204. {
  205. if (ocall_seekdir((void *)*dirp, loc) != SGX_SUCCESS) {
  206. TRACE_OCALL_FAIL();
  207. }
  208. }
  209. long telldir(DIR *dirp)
  210. {
  211. long ret;
  212. if (ocall_telldir(&ret, (void *)*dirp) != SGX_SUCCESS) {
  213. TRACE_OCALL_FAIL();
  214. return -1;
  215. }
  216. if (ret == -1)
  217. errno = get_errno();
  218. return ret;
  219. }
  220. int closedir(DIR *dirp)
  221. {
  222. int ret;
  223. if (ocall_closedir(&ret, (void *)*dirp) != SGX_SUCCESS) {
  224. TRACE_OCALL_FAIL();
  225. return -1;
  226. }
  227. BH_FREE(dirp);
  228. if (ret == -1)
  229. errno = get_errno();
  230. return ret;
  231. }
  232. static ssize_t
  233. readv_internal(int fd, const struct iovec *iov, int iovcnt,
  234. bool has_offset, off_t offset)
  235. {
  236. ssize_t ret, size_left;
  237. struct iovec *iov1;
  238. int i;
  239. char *p;
  240. uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
  241. if (iov == NULL || iovcnt < 1)
  242. return -1;
  243. for (i = 0; i < iovcnt; i++) {
  244. total_size += iov[i].iov_len;
  245. }
  246. if (total_size >= UINT32_MAX)
  247. return -1;
  248. iov1 = BH_MALLOC((uint32)total_size);
  249. if (iov1 == NULL)
  250. return -1;
  251. memset(iov1, 0, (uint32)total_size);
  252. p = (char*)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  253. for (i = 0; i < iovcnt; i++) {
  254. iov1[i].iov_len = iov[i].iov_len;
  255. iov1[i].iov_base = p;
  256. p += iov[i].iov_len;
  257. }
  258. if (ocall_readv(&ret, fd, (char *)iov1, (uint32)total_size,
  259. iovcnt, has_offset, offset) != SGX_SUCCESS) {
  260. TRACE_OCALL_FAIL();
  261. BH_FREE(iov1);
  262. return -1;
  263. }
  264. p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  265. size_left = ret;
  266. for (i = 0; i < iovcnt; i++) {
  267. if (size_left > iov[i].iov_len) {
  268. memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1,
  269. iov[i].iov_len);
  270. p += iov[i].iov_len;
  271. size_left -= iov[i].iov_len;
  272. }
  273. else {
  274. memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1,
  275. size_left);
  276. break;
  277. }
  278. }
  279. BH_FREE(iov1);
  280. if (ret == -1)
  281. errno = get_errno();
  282. return ret;
  283. }
  284. static ssize_t
  285. writev_internal(int fd, const struct iovec *iov, int iovcnt,
  286. bool has_offset, off_t offset)
  287. {
  288. ssize_t ret;
  289. struct iovec *iov1;
  290. int i;
  291. char *p;
  292. uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
  293. if (iov == NULL || iovcnt < 1)
  294. return -1;
  295. for (i = 0; i < iovcnt; i++) {
  296. total_size += iov[i].iov_len;
  297. }
  298. if (total_size >= UINT32_MAX)
  299. return -1;
  300. iov1 = BH_MALLOC((uint32)total_size);
  301. if (iov1 == NULL)
  302. return -1;
  303. memset(iov1, 0, (uint32)total_size);
  304. p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  305. for (i = 0; i < iovcnt; i++) {
  306. iov1[i].iov_len = iov[i].iov_len;
  307. iov1[i].iov_base = p;
  308. memcpy((uintptr_t)p + (char *)iov1, iov[i].iov_base,
  309. iov[i].iov_len);
  310. p += iov[i].iov_len;
  311. }
  312. if (ocall_writev(&ret, fd, (char *)iov1, (uint32)total_size,
  313. iovcnt, has_offset, offset) != SGX_SUCCESS) {
  314. TRACE_OCALL_FAIL();
  315. BH_FREE(iov1);
  316. return -1;
  317. }
  318. BH_FREE(iov1);
  319. if (ret == -1)
  320. errno = get_errno();
  321. return ret;
  322. }
  323. ssize_t readv(int fd, const struct iovec *iov, int iovcnt)
  324. {
  325. return readv_internal(fd, iov, iovcnt, false, 0);
  326. }
  327. ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
  328. {
  329. return writev_internal(fd, iov, iovcnt, false, 0);
  330. }
  331. ssize_t preadv(int fd, const struct iovec *iov, int iovcnt,
  332. off_t offset)
  333. {
  334. return readv_internal(fd, iov, iovcnt, true, offset);
  335. }
  336. ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt,
  337. off_t offset)
  338. {
  339. return writev_internal(fd, iov, iovcnt, true, offset);
  340. }
  341. off_t lseek(int fd, off_t offset, int whence)
  342. {
  343. off_t ret;
  344. if (ocall_lseek(&ret, fd, (long)offset, whence) != SGX_SUCCESS) {
  345. TRACE_OCALL_FAIL();
  346. return -1;
  347. }
  348. if (ret == -1)
  349. errno = get_errno();
  350. return ret;
  351. }
  352. int ftruncate(int fd, off_t length)
  353. {
  354. int ret;
  355. if (ocall_ftruncate(&ret, fd, length) != SGX_SUCCESS) {
  356. TRACE_OCALL_FAIL();
  357. return -1;
  358. }
  359. if (ret == -1)
  360. errno = get_errno();
  361. return ret;
  362. }
  363. int fstat(int fd, struct stat *statbuf)
  364. {
  365. int ret;
  366. if (statbuf == NULL)
  367. return -1;
  368. if (ocall_fstat(&ret, fd, (void *)statbuf,
  369. sizeof(struct stat)) != SGX_SUCCESS) {
  370. TRACE_OCALL_FAIL();
  371. return -1;
  372. }
  373. if (ret == -1)
  374. errno = get_errno();
  375. return ret;
  376. }
  377. int fstatat(int dirfd, const char *pathname, struct stat *statbuf,
  378. int flags)
  379. {
  380. int ret;
  381. if (statbuf == NULL)
  382. return -1;
  383. if (ocall_fstatat(&ret, dirfd, pathname, (void *)statbuf,
  384. sizeof(struct stat), flags) != SGX_SUCCESS) {
  385. TRACE_OCALL_FAIL();
  386. return -1;
  387. }
  388. if (ret == -1)
  389. errno = get_errno();
  390. return ret;
  391. }
  392. int fsync(int fd)
  393. {
  394. int ret;
  395. if (ocall_fsync(&ret, fd) != SGX_SUCCESS) {
  396. TRACE_OCALL_FAIL();
  397. return -1;
  398. }
  399. if (ret == -1)
  400. errno = get_errno();
  401. return ret;
  402. }
  403. int fdatasync(int fd)
  404. {
  405. int ret;
  406. if (ocall_fdatasync(&ret, fd) != SGX_SUCCESS) {
  407. TRACE_OCALL_FAIL();
  408. return -1;
  409. }
  410. if (ret == -1)
  411. errno = get_errno();
  412. return ret;
  413. }
  414. int mkdirat(int dirfd, const char *pathname, mode_t mode)
  415. {
  416. int ret;
  417. if (ocall_mkdirat(&ret, dirfd, pathname, mode) != SGX_SUCCESS) {
  418. TRACE_OCALL_FAIL();
  419. return -1;
  420. }
  421. if (ret == -1)
  422. errno = get_errno();
  423. return ret;
  424. }
  425. int link(const char *oldpath, const char *newpath)
  426. {
  427. int ret;
  428. if (ocall_link(&ret, oldpath, newpath) != SGX_SUCCESS) {
  429. TRACE_OCALL_FAIL();
  430. return -1;
  431. }
  432. if (ret == -1)
  433. errno = get_errno();
  434. return ret;
  435. }
  436. int linkat(int olddirfd, const char *oldpath,
  437. int newdirfd, const char *newpath, int flags)
  438. {
  439. int ret;
  440. if (ocall_linkat(&ret, olddirfd, oldpath, newdirfd, newpath,
  441. flags) != SGX_SUCCESS) {
  442. TRACE_OCALL_FAIL();
  443. return -1;
  444. }
  445. if (ret == -1)
  446. errno = get_errno();
  447. return ret;
  448. }
  449. int unlinkat(int dirfd, const char *pathname, int flags)
  450. {
  451. int ret;
  452. if (ocall_unlinkat(&ret, dirfd, pathname, flags) != SGX_SUCCESS) {
  453. TRACE_OCALL_FAIL();
  454. return -1;
  455. }
  456. if (ret == -1)
  457. errno = get_errno();
  458. return ret;
  459. }
  460. ssize_t readlinkat(int dirfd, const char *pathname,
  461. char *buf, size_t bufsiz)
  462. {
  463. ssize_t ret;
  464. if (buf == NULL)
  465. return -1;
  466. if (ocall_readlinkat(&ret, dirfd, pathname, buf,
  467. bufsiz) != SGX_SUCCESS) {
  468. TRACE_OCALL_FAIL();
  469. return -1;
  470. }
  471. if (ret == -1)
  472. errno = get_errno();
  473. return ret;
  474. }
  475. int symlinkat(const char *target, int newdirfd, const char *linkpath)
  476. {
  477. int ret;
  478. if (ocall_symlinkat(&ret, target,
  479. newdirfd, linkpath) != SGX_SUCCESS) {
  480. TRACE_OCALL_FAIL();
  481. return -1;
  482. }
  483. if (ret == -1)
  484. errno = get_errno();
  485. return ret;
  486. }
  487. int renameat(int olddirfd, const char *oldpath,
  488. int newdirfd, const char *newpath)
  489. {
  490. int ret;
  491. if (ocall_renameat(&ret, olddirfd, oldpath,
  492. newdirfd, newpath) != SGX_SUCCESS) {
  493. TRACE_OCALL_FAIL();
  494. return -1;
  495. }
  496. if (ret == -1)
  497. errno = get_errno();
  498. return ret;
  499. }
  500. int ioctl(int fd, unsigned long request, ...)
  501. {
  502. int ret;
  503. va_list args;
  504. switch (request) {
  505. case FIONREAD:
  506. va_start(args, request);
  507. int *arg = (int *)va_arg(args, int *);
  508. if (ocall_ioctl(&ret, fd, request, arg,
  509. sizeof(*arg)) != SGX_SUCCESS) {
  510. TRACE_OCALL_FAIL();
  511. va_end(args);
  512. return -1;
  513. }
  514. va_end(args);
  515. break;
  516. default:
  517. os_printf("ioctl failed: unknown request", request);
  518. return -1;
  519. }
  520. if (ret == -1)
  521. errno = get_errno();
  522. return ret;
  523. }
  524. int fcntl(int fd, int cmd, ... /* arg */ )
  525. {
  526. int ret;
  527. va_list args;
  528. switch (cmd) {
  529. case F_GETFD:
  530. case F_GETFL:
  531. if (ocall_fcntl(&ret, fd, cmd) != SGX_SUCCESS) {
  532. TRACE_OCALL_FAIL();
  533. return -1;
  534. }
  535. break;
  536. case F_DUPFD:
  537. case F_SETFD:
  538. case F_SETFL:
  539. va_start(args, cmd);
  540. long arg_1 = (long)va_arg(args, long);
  541. if (ocall_fcntl_long(&ret, fd, cmd, arg_1) != SGX_SUCCESS) {
  542. TRACE_OCALL_FAIL();
  543. va_end(args);
  544. return -1;
  545. }
  546. va_end(args);
  547. break;
  548. default:
  549. os_printf("fcntl failed: unknown cmd %d.\n", cmd);
  550. return -1;
  551. }
  552. if (ret == -1)
  553. errno = get_errno();
  554. return ret;
  555. }
  556. int isatty(int fd)
  557. {
  558. int ret;
  559. if (ocall_isatty(&ret, fd) != SGX_SUCCESS) {
  560. TRACE_OCALL_FAIL();
  561. return -1;
  562. }
  563. if (ret == 0)
  564. errno = get_errno();
  565. return ret;
  566. }
  567. char *realpath(const char *path, char *resolved_path)
  568. {
  569. int ret;
  570. char buf[PATH_MAX] = { 0 };
  571. if (ocall_realpath(&ret, path, buf, PATH_MAX) != SGX_SUCCESS) {
  572. TRACE_OCALL_FAIL();
  573. return (char *)NULL;
  574. }
  575. if (ret != 0)
  576. return (char *)NULL;
  577. if (resolved_path) {
  578. strcpy(resolved_path, buf);
  579. }
  580. else {
  581. resolved_path = BH_MALLOC(strlen(buf) + 1);
  582. if (resolved_path == NULL)
  583. return NULL;
  584. strcpy(resolved_path, buf);
  585. }
  586. return resolved_path;
  587. }
  588. int posix_fallocate(int fd, off_t offset, off_t len)
  589. {
  590. int ret;
  591. if (ocall_posix_fallocate(&ret, fd, offset, len) != SGX_SUCCESS) {
  592. TRACE_OCALL_FAIL();
  593. return -1;
  594. }
  595. return ret;
  596. }
  597. int poll(struct pollfd *fds, nfds_t nfds, int timeout)
  598. {
  599. int ret;
  600. if (fds == NULL)
  601. return -1;
  602. if (ocall_poll(&ret, fds, nfds, timeout,
  603. sizeof(*fds) * nfds) != SGX_SUCCESS) {
  604. TRACE_OCALL_FAIL();
  605. return -1;
  606. }
  607. if (ret == -1)
  608. errno = get_errno();
  609. return ret;
  610. }
  611. int getopt(int argc, char * const argv[],
  612. const char *optstring)
  613. {
  614. int ret;
  615. char **argv1;
  616. char *p;
  617. int i;
  618. uint64 total_size = sizeof(char *) * (uint64)argc;
  619. for (i = 0; i < argc; i++) {
  620. total_size += strlen(argv[i]) + 1;
  621. }
  622. if (total_size >= UINT32_MAX)
  623. return -1;
  624. argv1 = BH_MALLOC((uint32)total_size);
  625. if (argv1 == NULL)
  626. return -1;
  627. p = (char *)(uintptr_t)(sizeof(char *) * argc);
  628. for (i = 0; i < argc; i++) {
  629. argv1[i] = p;
  630. strcpy((char *)argv1 + (uintptr_t)p, argv[i]);
  631. p += ((uintptr_t)strlen(argv[i]) + 1);
  632. }
  633. if (ocall_getopt(&ret, argc, (char *)argv1, total_size,
  634. optstring) != SGX_SUCCESS) {
  635. TRACE_OCALL_FAIL();
  636. BH_FREE(argv1);
  637. return -1;
  638. }
  639. BH_FREE(argv1);
  640. if (ret == -1)
  641. errno = get_errno();
  642. return ret;
  643. }
  644. int sched_yield(void)
  645. {
  646. int ret;
  647. if (ocall_sched_yield(&ret) != SGX_SUCCESS) {
  648. TRACE_OCALL_FAIL();
  649. return -1;
  650. }
  651. if (ret == -1)
  652. errno = get_errno();
  653. return ret;
  654. }
  655. ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
  656. {
  657. ssize_t ret;
  658. if (ocall_getrandom(&ret, buf, buflen, flags) != SGX_SUCCESS) {
  659. TRACE_OCALL_FAIL();
  660. return -1;
  661. }
  662. if (ret == -1)
  663. errno = get_errno();
  664. return ret;
  665. }
  666. int get_errno(void)
  667. {
  668. int ret;
  669. if (ocall_get_errno(&ret) != SGX_SUCCESS) {
  670. TRACE_OCALL_FAIL();
  671. return -1;
  672. }
  673. return ret;
  674. }
  675. #endif