shim_fs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  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. * shim_fs.c
  15. *
  16. * Implementation of system call "unlink", "unlinkat", "mkdir", "mkdirat",
  17. * "rmdir", "umask", "chmod", "fchmod", "fchmodat", "rename", "renameat" and
  18. * "sendfile".
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_table.h>
  22. #include <shim_utils.h>
  23. #include <shim_thread.h>
  24. #include <shim_handle.h>
  25. #include <shim_fs.h>
  26. #include <pal.h>
  27. #include <pal_error.h>
  28. #include <errno.h>
  29. #include <linux/fcntl.h>
  30. #include <linux/stat.h>
  31. #include <asm/mman.h>
  32. /* The kernel would look up the parent directory, and remove the child from
  33. * the inode. But we are working with the PAL, so we open the file, truncate
  34. * and close it. */
  35. int shim_do_unlink (const char * file)
  36. {
  37. if (!file)
  38. return -EINVAL;
  39. if (test_user_string(file))
  40. return -EFAULT;
  41. struct shim_dentry * dent = NULL;
  42. int ret = 0;
  43. if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent, NULL)) < 0)
  44. return ret;
  45. if (!dent->parent)
  46. return -EACCES;
  47. if (dent->state & DENTRY_ISDIRECTORY)
  48. return -EISDIR;
  49. if (dent->fs && dent->fs->d_ops &&
  50. dent->fs->d_ops->unlink) {
  51. if ((ret = dent->fs->d_ops->unlink(dent->parent, dent)) < 0)
  52. return ret;
  53. } else
  54. dent->state |= DENTRY_PERSIST;
  55. dent->state |= DENTRY_NEGATIVE;
  56. put_dentry(dent);
  57. return 0;
  58. }
  59. int shim_do_unlinkat (int dfd, const char * pathname, int flag)
  60. {
  61. if (!pathname)
  62. return -EINVAL;
  63. if (test_user_string(pathname))
  64. return -EFAULT;
  65. if (flag & ~AT_REMOVEDIR)
  66. return -EINVAL;
  67. struct shim_dentry * dir = NULL, * dent = NULL;
  68. int ret = 0;
  69. if ((ret = get_dirfd_dentry(dfd, &dir)) < 0)
  70. return ret;
  71. if ((ret = path_lookupat(dir, pathname, LOOKUP_OPEN, &dent, NULL)) < 0)
  72. goto out;
  73. if (!dent->parent) {
  74. ret = -EACCES;
  75. goto out_dent;
  76. }
  77. if (flag & AT_REMOVEDIR) {
  78. if (!(dent->state & DENTRY_ISDIRECTORY))
  79. return -ENOTDIR;
  80. } else {
  81. if (dent->state & DENTRY_ISDIRECTORY)
  82. return -EISDIR;
  83. }
  84. if (dent->fs && dent->fs->d_ops &&
  85. dent->fs->d_ops->unlink) {
  86. if ((ret = dent->fs->d_ops->unlink(dent->parent, dent)) < 0)
  87. return ret;
  88. } else
  89. dent->state |= DENTRY_PERSIST;
  90. if (flag & AT_REMOVEDIR)
  91. dent->state &= ~DENTRY_ISDIRECTORY;
  92. dent->state |= DENTRY_NEGATIVE;
  93. out_dent:
  94. put_dentry(dent);
  95. out:
  96. put_dentry(dir);
  97. return ret;
  98. }
  99. int shim_do_mkdir (const char * pathname, int mode)
  100. {
  101. return open_namei(NULL, NULL, pathname, O_CREAT|O_EXCL|O_DIRECTORY,
  102. mode, NULL);
  103. }
  104. int shim_do_mkdirat (int dfd, const char * pathname, int mode)
  105. {
  106. if (!pathname)
  107. return -EINVAL;
  108. if (test_user_string(pathname))
  109. return -EFAULT;
  110. struct shim_dentry * dir = NULL;
  111. int ret = 0;
  112. if ((ret = get_dirfd_dentry(dfd, &dir)) < 0)
  113. return ret;
  114. ret = open_namei(NULL, dir, pathname, O_CREAT|O_EXCL|O_DIRECTORY,
  115. mode, NULL);
  116. put_dentry(dir);
  117. return ret;
  118. }
  119. int shim_do_rmdir (const char * pathname)
  120. {
  121. int ret = 0;
  122. struct shim_dentry * dent = NULL;
  123. if (!pathname)
  124. return -EINVAL;
  125. if (test_user_string(pathname))
  126. return -EFAULT;
  127. if ((ret = path_lookupat(NULL, pathname, LOOKUP_OPEN|LOOKUP_DIRECTORY,
  128. &dent, NULL)) < 0)
  129. return ret;
  130. if (!dent->parent) {
  131. ret = -EACCES;
  132. goto out;
  133. }
  134. if (!(dent->state & DENTRY_ISDIRECTORY)) {
  135. ret = -ENOTDIR;
  136. goto out;
  137. }
  138. if (dent->fs && dent->fs->d_ops &&
  139. dent->fs->d_ops->unlink) {
  140. if ((ret = dent->fs->d_ops->unlink(dent->parent, dent)) < 0)
  141. goto out;
  142. } else
  143. dent->state |= DENTRY_PERSIST;
  144. dent->state &= ~DENTRY_ISDIRECTORY;
  145. dent->state |= DENTRY_NEGATIVE;
  146. out:
  147. put_dentry(dent);
  148. return 0;
  149. }
  150. mode_t shim_do_umask (mode_t mask)
  151. {
  152. struct shim_thread * cur = get_cur_thread();
  153. lock(&cur->lock);
  154. mode_t old = cur->umask;
  155. cur->umask = mask & 0777;
  156. unlock(&cur->lock);
  157. return old;
  158. }
  159. int shim_do_chmod (const char * path, mode_t mode)
  160. {
  161. struct shim_dentry * dent = NULL;
  162. int ret = 0;
  163. if (test_user_string(path))
  164. return -EFAULT;
  165. if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent, NULL)) < 0)
  166. return ret;
  167. if (dent->fs && dent->fs->d_ops &&
  168. dent->fs->d_ops->chmod) {
  169. if ((ret = dent->fs->d_ops->chmod(dent, mode)) < 0)
  170. goto out;
  171. } else
  172. dent->state |= DENTRY_PERSIST;
  173. dent->mode = mode;
  174. out:
  175. put_dentry(dent);
  176. return ret;
  177. }
  178. int shim_do_fchmodat (int dfd, const char * filename, mode_t mode)
  179. {
  180. if (!filename)
  181. return -EINVAL;
  182. if (test_user_string(filename))
  183. return -EFAULT;
  184. struct shim_dentry * dir = NULL, * dent = NULL;
  185. int ret = 0;
  186. if ((ret = get_dirfd_dentry(dfd, &dir)) < 0)
  187. return ret;
  188. if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent, NULL)) < 0)
  189. goto out;
  190. if (dent->fs && dent->fs->d_ops &&
  191. dent->fs->d_ops->chmod) {
  192. if ((ret = dent->fs->d_ops->chmod(dent, mode)) < 0)
  193. goto out_dent;
  194. } else
  195. dent->state |= DENTRY_PERSIST;
  196. dent->mode = mode;
  197. out_dent:
  198. put_dentry(dent);
  199. out:
  200. put_dentry(dir);
  201. return ret;
  202. }
  203. int shim_do_fchmod (int fd, mode_t mode)
  204. {
  205. struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL);
  206. if (!hdl)
  207. return -EBADF;
  208. struct shim_dentry * dent = hdl->dentry;
  209. int ret = 0;
  210. if (dent->fs && dent->fs->d_ops && dent->fs->d_ops->chmod) {
  211. if ((ret = dent->fs->d_ops->chmod(dent, mode)) < 0)
  212. goto out;
  213. } else {
  214. dent->state |= DENTRY_PERSIST;
  215. }
  216. dent->mode = mode;
  217. out:
  218. put_handle(hdl);
  219. return ret;
  220. }
  221. int shim_do_chown (const char * path, uid_t uid, gid_t gid)
  222. {
  223. struct shim_dentry * dent = NULL;
  224. int ret = 0;
  225. __UNUSED(uid);
  226. __UNUSED(gid);
  227. if (!path)
  228. return -EINVAL;
  229. if (test_user_string(path))
  230. return -EFAULT;
  231. if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent, NULL)) < 0)
  232. return ret;
  233. /* XXX: do nothing now */
  234. put_dentry(dent);
  235. return ret;
  236. }
  237. int shim_do_fchownat (int dfd, const char * filename, uid_t uid, gid_t gid,
  238. int flags)
  239. {
  240. __UNUSED(flags);
  241. __UNUSED(uid);
  242. __UNUSED(gid);
  243. if (!filename)
  244. return -EINVAL;
  245. if (test_user_string(filename))
  246. return -EFAULT;
  247. struct shim_dentry * dir = NULL, * dent = NULL;
  248. int ret = 0;
  249. if ((ret = get_dirfd_dentry(dfd, &dir)) < 0)
  250. return ret;
  251. if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent, NULL)) < 0)
  252. goto out;
  253. /* XXX: do nothing now */
  254. put_dentry(dent);
  255. out:
  256. put_dentry(dir);
  257. return ret;
  258. }
  259. int shim_do_fchown (int fd, uid_t uid, gid_t gid)
  260. {
  261. __UNUSED(uid);
  262. __UNUSED(gid);
  263. struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL);
  264. if (!hdl)
  265. return -EBADF;
  266. /* XXX: do nothing now */
  267. return 0;
  268. }
  269. #define MAP_SIZE (g_pal_alloc_align * 4)
  270. #define BUF_SIZE 2048
  271. static ssize_t handle_copy (struct shim_handle * hdli, off_t * offseti,
  272. struct shim_handle * hdlo, off_t * offseto,
  273. ssize_t count)
  274. {
  275. struct shim_mount * fsi = hdli->fs;
  276. struct shim_mount * fso = hdlo->fs;
  277. if (!count)
  278. return 0;
  279. if (!fsi || !fsi->fs_ops || !fso || !fso->fs_ops)
  280. return -EACCES;
  281. bool do_mapi = (fsi->fs_ops->mmap != NULL);
  282. bool do_mapo = (fso->fs_ops->mmap != NULL);
  283. bool do_marki = false, do_marko = false;
  284. int offi = 0, offo = 0;
  285. if (offseti) {
  286. if (!fsi->fs_ops->seek)
  287. return -EACCES;
  288. offi = *offseti;
  289. fsi->fs_ops->seek(hdli, offi, SEEK_SET);
  290. } else {
  291. if (!fsi->fs_ops->seek ||
  292. (offi = fsi->fs_ops->seek(hdli, 0, SEEK_CUR)) < 0)
  293. do_mapi = false;
  294. }
  295. if (offseto) {
  296. if (!fso->fs_ops->seek)
  297. return -EACCES;
  298. offo = *offseto;
  299. fso->fs_ops->seek(hdlo, offo, SEEK_SET);
  300. } else {
  301. if (!fso->fs_ops->seek ||
  302. (offo = fso->fs_ops->seek(hdlo, 0, SEEK_CUR)) < 0)
  303. do_mapo = false;
  304. }
  305. if (do_mapi) {
  306. int size;
  307. if (fsi->fs_ops->poll &&
  308. (size = fsi->fs_ops->poll(hdli, FS_POLL_SZ)) >= 0) {
  309. if (count == -1 ||
  310. count > size - offi)
  311. count = size - offi;
  312. if (!count)
  313. return 0;
  314. } else
  315. do_mapi = false;
  316. }
  317. if (do_mapo && count > 0)
  318. do {
  319. int size;
  320. if (!fso->fs_ops->poll ||
  321. (size = fso->fs_ops->poll(hdlo, FS_POLL_SZ)) < 0) {
  322. do_mapo = false;
  323. break;
  324. }
  325. if (offo + count < size)
  326. break;
  327. if (!fso->fs_ops->truncate ||
  328. fso->fs_ops->truncate(hdlo, offo + count) < 0) {
  329. do_mapo = false;
  330. break;
  331. }
  332. } while(0);
  333. void * bufi = NULL, * bufo = NULL;
  334. int bytes = 0;
  335. int bufsize = MAP_SIZE;
  336. int copysize = 0;
  337. if (!do_mapi && (hdli->flags & O_NONBLOCK) &&
  338. fsi->fs_ops->setflags) {
  339. int ret = fsi->fs_ops->setflags(hdli, 0);
  340. if (!ret) {
  341. debug("mark handle %s as blocking\n", qstrgetstr(&hdli->uri));
  342. do_marki = true;
  343. }
  344. }
  345. if (!do_mapo && (hdlo->flags & O_NONBLOCK) &&
  346. fso->fs_ops->setflags) {
  347. int ret = fso->fs_ops->setflags(hdlo, 0);
  348. if (!ret) {
  349. debug("mark handle %s as blocking\n", qstrgetstr(&hdlo->uri));
  350. do_marko = true;
  351. }
  352. }
  353. assert(count);
  354. do {
  355. int boffi = 0, boffo = 0;
  356. int expectsize = bufsize;
  357. if (count > 0 && bufsize > count - bytes)
  358. expectsize = bufsize = count - bytes;
  359. if (do_mapi && !bufi) {
  360. boffi = offi - PAGE_ALIGN_DOWN(offi);
  361. if (fsi->fs_ops->mmap(hdli, &bufi, PAGE_ALIGN_UP(bufsize + boffi),
  362. PROT_READ, MAP_FILE, offi - boffi) < 0) {
  363. do_mapi = false;
  364. boffi = 0;
  365. if ((hdli->flags & O_NONBLOCK) && fsi->fs_ops->setflags) {
  366. int ret = fsi->fs_ops->setflags(hdli, 0);
  367. if (!ret) {
  368. debug("mark handle %s as blocking\n",
  369. qstrgetstr(&hdli->uri));
  370. do_marki = true;
  371. }
  372. }
  373. if (fsi->fs_ops->seek)
  374. offi = fsi->fs_ops->seek(hdli, offi, SEEK_SET);
  375. }
  376. }
  377. if (do_mapo && !bufo) {
  378. boffo = offo - PAGE_ALIGN_DOWN(offo);
  379. if (fso->fs_ops->mmap(hdlo, &bufo, PAGE_ALIGN_UP(bufsize + boffo),
  380. PROT_WRITE, MAP_FILE, offo - boffo) < 0) {
  381. do_mapo = false;
  382. boffo = 0;
  383. if ((hdlo->flags & O_NONBLOCK) && fso->fs_ops->setflags) {
  384. int ret = fso->fs_ops->setflags(hdlo, 0);
  385. if (!ret) {
  386. debug("mark handle %s as blocking\n",
  387. qstrgetstr(&hdlo->uri));
  388. do_marko = true;
  389. }
  390. }
  391. if (fso->fs_ops->seek)
  392. offo = fso->fs_ops->seek(hdlo, offo, SEEK_SET);
  393. }
  394. }
  395. if (do_mapi && do_mapo) {
  396. copysize = count - bytes > bufsize ? bufsize :
  397. count - bytes;
  398. memcpy(bufo + boffo, bufi + boffi, copysize);
  399. DkVirtualMemoryFree(bufi, PAGE_ALIGN_UP(bufsize + boffi));
  400. bufi = NULL;
  401. DkVirtualMemoryFree(bufo, PAGE_ALIGN_UP(bufsize + boffo));
  402. bufo = NULL;
  403. } else if (do_mapo) {
  404. copysize = fsi->fs_ops->read(hdli, bufo + boffo, bufsize);
  405. DkVirtualMemoryFree(bufo, PAGE_ALIGN_UP(bufsize + boffo));
  406. bufo = NULL;
  407. if (copysize < 0)
  408. break;
  409. } else if (do_mapi) {
  410. copysize = fso->fs_ops->write(hdlo, bufi + boffi, bufsize);
  411. DkVirtualMemoryFree(bufi, PAGE_ALIGN_UP(bufsize + boffi));
  412. bufi = NULL;
  413. if (copysize < 0)
  414. break;
  415. } else {
  416. if (!bufi)
  417. bufi = __alloca((bufsize = (bufsize > BUF_SIZE) ? BUF_SIZE :
  418. bufsize));
  419. copysize = fsi->fs_ops->read(hdli, bufi, bufsize);
  420. if (copysize <= 0)
  421. break;
  422. expectsize = copysize;
  423. copysize = fso->fs_ops->write(hdlo, bufi, expectsize);
  424. if (copysize < 0)
  425. break;
  426. }
  427. debug("copy %d bytes\n", copysize);
  428. bytes += copysize;
  429. offi += copysize;
  430. offo += copysize;
  431. if (copysize < expectsize)
  432. break;
  433. } while (bytes < count);
  434. if (copysize < 0 || (count > 0 && bytes < count)) {
  435. int ret = copysize < 0 ? copysize : -EAGAIN;
  436. if (bytes) {
  437. if (fsi->fs_ops->seek)
  438. fsi->fs_ops->seek(hdli, offi - bytes, SEEK_SET);
  439. if (fso->fs_ops->seek)
  440. fso->fs_ops->seek(hdlo, offo - bytes, SEEK_SET);
  441. }
  442. return ret;
  443. }
  444. if (do_marki && (hdli->flags & O_NONBLOCK)) {
  445. debug("mark handle %s as nonblocking\n", qstrgetstr(&hdli->uri));
  446. fsi->fs_ops->setflags(hdli, O_NONBLOCK);
  447. }
  448. if (do_marko && (hdlo->flags & O_NONBLOCK)) {
  449. debug("mark handle %s as nonblocking\n", qstrgetstr(&hdlo->uri));
  450. fso->fs_ops->setflags(hdlo, O_NONBLOCK);
  451. }
  452. if (do_mapi) {
  453. if (fsi->fs_ops->seek)
  454. fsi->fs_ops->seek(hdli, offi, SEEK_SET);
  455. }
  456. if (offseti)
  457. *offseti = offi;
  458. if (do_mapo) {
  459. if (fso->fs_ops->seek)
  460. fso->fs_ops->seek(hdlo, offo, SEEK_SET);
  461. }
  462. if (offseto)
  463. *offseto = offo;
  464. return bytes;
  465. }
  466. static int do_rename(struct shim_dentry* old_dent, struct shim_dentry* new_dent) {
  467. if ((old_dent->type != S_IFREG)
  468. || (!(new_dent->state & DENTRY_NEGATIVE) && (new_dent->type != S_IFREG))) {
  469. /* Current implementation of fs does not allow for renaming anything but regular files */
  470. return -ENOSYS;
  471. }
  472. if (old_dent->fs != new_dent->fs) {
  473. /* Disallow cross mount renames */
  474. return -EXDEV;
  475. }
  476. if (!old_dent->fs || !old_dent->fs->d_ops || !old_dent->fs->d_ops->rename) {
  477. return -EPERM;
  478. }
  479. if (old_dent->state & DENTRY_ISDIRECTORY) {
  480. if (!(new_dent->state & DENTRY_NEGATIVE)) {
  481. if (!(new_dent->state & DENTRY_ISDIRECTORY)) {
  482. return -ENOTDIR;
  483. }
  484. if (new_dent->nchildren > 0) {
  485. return -ENOTEMPTY;
  486. }
  487. } else {
  488. /* destination is a negative dentry and needs to be marked as a directory,
  489. * since source is a directory */
  490. new_dent->state |= DENTRY_ISDIRECTORY;
  491. }
  492. } else if (new_dent->state & DENTRY_ISDIRECTORY) {
  493. return -EISDIR;
  494. }
  495. if (dentry_is_ancestor(old_dent, new_dent) || dentry_is_ancestor(new_dent, old_dent)) {
  496. return -EINVAL;
  497. }
  498. /* TODO: Add appropriate checks for hardlinks once they get implemented. */
  499. int ret = old_dent->fs->d_ops->rename(old_dent, new_dent);
  500. if (!ret) {
  501. old_dent->state |= DENTRY_NEGATIVE;
  502. new_dent->state &= ~DENTRY_NEGATIVE;
  503. }
  504. return ret;
  505. }
  506. int shim_do_rename(const char* oldpath, const char* newpath) {
  507. return shim_do_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
  508. }
  509. int shim_do_renameat(int olddirfd, const char* oldpath, int newdirfd, const char* newpath) {
  510. struct shim_dentry* old_dir_dent = NULL;
  511. struct shim_dentry* old_dent = NULL;
  512. struct shim_dentry* new_dir_dent = NULL;
  513. struct shim_dentry* new_dent = NULL;
  514. int ret = 0;
  515. if (!oldpath || test_user_string(oldpath) || !newpath || test_user_string(newpath)) {
  516. return -EFAULT;
  517. }
  518. if ((ret = get_dirfd_dentry(olddirfd, &old_dir_dent)) < 0) {
  519. goto out;
  520. }
  521. if ((ret = path_lookupat(old_dir_dent, oldpath, LOOKUP_OPEN, &old_dent, NULL)) < 0) {
  522. goto out;
  523. }
  524. if (old_dent->state & DENTRY_NEGATIVE) {
  525. ret = -ENOENT;
  526. goto out;
  527. }
  528. if ((ret = get_dirfd_dentry(newdirfd, &new_dir_dent)) < 0) {
  529. goto out;
  530. }
  531. ret = path_lookupat(new_dir_dent, newpath, LOOKUP_OPEN|LOOKUP_CREATE, &new_dent, NULL);
  532. if (ret < 0) {
  533. if (ret != -ENOENT
  534. || !new_dent
  535. || (new_dent->state & (DENTRY_NEGATIVE|DENTRY_VALID))
  536. != (DENTRY_NEGATIVE|DENTRY_VALID)) {
  537. goto out;
  538. }
  539. }
  540. // Both dentries should have a ref count of at least 2 at this point
  541. assert(REF_GET(old_dent->ref_count) >= 2);
  542. assert(REF_GET(new_dent->ref_count) >= 2);
  543. ret = do_rename(old_dent, new_dent);
  544. out:
  545. if (old_dir_dent)
  546. put_dentry(old_dir_dent);
  547. if (old_dent)
  548. put_dentry(old_dent);
  549. if (new_dir_dent)
  550. put_dentry(new_dir_dent);
  551. if (new_dent)
  552. put_dentry(new_dent);
  553. return ret;
  554. }
  555. ssize_t shim_do_sendfile (int ofd, int ifd, off_t * offset,
  556. size_t count)
  557. {
  558. struct shim_handle * hdli = get_fd_handle(ifd, NULL, NULL);
  559. struct shim_handle * hdlo = get_fd_handle(ofd, NULL, NULL);
  560. if (!hdli || !hdlo)
  561. return -EBADF;
  562. off_t old_offset = 0;
  563. int ret = -EACCES;
  564. if (offset) {
  565. if (!hdli->fs || !hdli->fs->fs_ops ||
  566. !hdli->fs->fs_ops->seek)
  567. goto out;
  568. old_offset = hdli->fs->fs_ops->seek(hdli, 0, SEEK_CUR);
  569. if (old_offset < 0) {
  570. ret = old_offset;
  571. goto out;
  572. }
  573. }
  574. ret = handle_copy(hdli, offset, hdlo, NULL, count);
  575. if (ret >= 0 && offset)
  576. hdli->fs->fs_ops->seek(hdli, old_offset, SEEK_SET);
  577. out:
  578. put_handle(hdli);
  579. put_handle(hdlo);
  580. return ret;
  581. }
  582. int shim_do_chroot (const char * filename)
  583. {
  584. int ret = 0;
  585. struct shim_dentry * dent = NULL;
  586. if ((ret = path_lookupat(NULL, filename, 0 , &dent, NULL)) < 0)
  587. goto out;
  588. if (!dent) {
  589. ret = -ENOENT;
  590. goto out;
  591. }
  592. struct shim_thread * thread = get_cur_thread();
  593. lock(&thread->lock);
  594. put_dentry(thread->root);
  595. thread->root = dent;
  596. unlock(&thread->lock);
  597. out:
  598. return ret;
  599. }