linux_file.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. /* $OpenBSD: linux_file.c,v 1.30 2014/03/26 05:23:42 guenther Exp $ */
  2. /* $NetBSD: linux_file.c,v 1.15 1996/05/20 01:59:09 fvdl Exp $ */
  3. /*
  4. * Copyright (c) 1995 Frank van der Linden
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. All advertising materials mentioning features or use of this software
  16. * must display the following acknowledgement:
  17. * This product includes software developed for the NetBSD Project
  18. * by Frank van der Linden
  19. * 4. The name of the author may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  27. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <sys/param.h>
  34. #include <sys/systm.h>
  35. #include <sys/namei.h>
  36. #include <sys/proc.h>
  37. #include <sys/file.h>
  38. #include <sys/stat.h>
  39. #include <sys/filedesc.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/kernel.h>
  42. #include <sys/mount.h>
  43. #include <sys/signalvar.h>
  44. #include <sys/uio.h>
  45. #include <sys/malloc.h>
  46. #include <sys/vnode.h>
  47. #include <sys/tty.h>
  48. #include <sys/conf.h>
  49. #include <sys/stdint.h>
  50. #include <sys/syscallargs.h>
  51. #include <compat/linux/linux_types.h>
  52. #include <compat/linux/linux_signal.h>
  53. #include <compat/linux/linux_syscallargs.h>
  54. #include <compat/linux/linux_fcntl.h>
  55. #include <compat/linux/linux_util.h>
  56. #include <machine/linux_machdep.h>
  57. static int linux_to_bsd_ioflags(int);
  58. static int bsd_to_linux_ioflags(int);
  59. static void bsd_to_linux_flock(struct flock *, struct linux_flock *);
  60. static void linux_to_bsd_flock(struct linux_flock *, struct flock *);
  61. static int bsd_to_linux_stat(struct stat *, struct linux_stat *);
  62. static int linux_stat1(struct proc *, void *, register_t *, int);
  63. /*
  64. * Some file-related calls are handled here. The usual flag conversion
  65. * an structure conversion is done, and alternate emul path searching.
  66. */
  67. /*
  68. * The next two functions convert between the Linux and OpenBSD values
  69. * of the flags used in open(2) and fcntl(2).
  70. */
  71. static int
  72. linux_to_bsd_ioflags(lflags)
  73. int lflags;
  74. {
  75. int res = 0;
  76. res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
  77. res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
  78. res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
  79. res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
  80. res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
  81. res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
  82. res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
  83. res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
  84. res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_SYNC);
  85. res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
  86. res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
  87. return res;
  88. }
  89. static int
  90. bsd_to_linux_ioflags(bflags)
  91. int bflags;
  92. {
  93. int res = 0;
  94. res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
  95. res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
  96. res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
  97. res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
  98. res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
  99. res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
  100. res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
  101. res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
  102. res |= cvtto_linux_mask(bflags, O_SYNC, LINUX_O_SYNC);
  103. res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
  104. res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
  105. return res;
  106. }
  107. /*
  108. * creat(2) is an obsolete function, but it's present as a Linux
  109. * system call, so let's deal with it.
  110. *
  111. * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
  112. */
  113. int
  114. linux_sys_creat(p, v, retval)
  115. struct proc *p;
  116. void *v;
  117. register_t *retval;
  118. {
  119. struct linux_sys_creat_args /* {
  120. syscallarg(char *) path;
  121. syscallarg(int) mode;
  122. } */ *uap = v;
  123. struct sys_open_args oa;
  124. caddr_t sg;
  125. sg = stackgap_init(p);
  126. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  127. SCARG(&oa, path) = SCARG(uap, path);
  128. SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
  129. SCARG(&oa, mode) = SCARG(uap, mode);
  130. return sys_open(p, &oa, retval);
  131. }
  132. /*
  133. * open(2). Take care of the different flag values, and let the
  134. * OpenBSD syscall do the real work. See if this operation
  135. * gives the current process a controlling terminal.
  136. * (XXX is this necessary?)
  137. */
  138. int
  139. linux_sys_open(p, v, retval)
  140. struct proc *p;
  141. void *v;
  142. register_t *retval;
  143. {
  144. struct linux_sys_open_args /* {
  145. syscallarg(char *) path;
  146. syscallarg(int) flags;
  147. syscallarg(int) mode;
  148. } */ *uap = v;
  149. int error, fl;
  150. struct sys_open_args boa;
  151. caddr_t sg;
  152. sg = stackgap_init(p);
  153. fl = linux_to_bsd_ioflags(SCARG(uap, flags));
  154. if (fl & O_CREAT)
  155. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  156. else
  157. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  158. SCARG(&boa, path) = SCARG(uap, path);
  159. SCARG(&boa, flags) = fl;
  160. SCARG(&boa, mode) = SCARG(uap, mode);
  161. if ((error = sys_open(p, &boa, retval)))
  162. return error;
  163. /*
  164. * this bit from sunos_misc.c (and svr4_fcntl.c).
  165. * If we are a session leader, and we don't have a controlling
  166. * terminal yet, and the O_NOCTTY flag is not set, try to make
  167. * this the controlling terminal.
  168. */
  169. if (!(fl & O_NOCTTY) && SESS_LEADER(p->p_p) &&
  170. !(p->p_p->ps_flags & PS_CONTROLT)) {
  171. struct filedesc *fdp = p->p_fd;
  172. struct file *fp;
  173. if ((fp = fd_getfile(fdp, *retval)) == NULL)
  174. return (EBADF);
  175. FREF(fp);
  176. if (fp->f_type == DTYPE_VNODE)
  177. (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
  178. FRELE(fp, p);
  179. }
  180. return 0;
  181. }
  182. int
  183. linux_sys_lseek(p, v, retval)
  184. struct proc *p;
  185. void *v;
  186. register_t *retval;
  187. {
  188. struct linux_sys_lseek_args /* {
  189. syscallarg(int) fd;
  190. syscallarg(long) offset;
  191. syscallarg(int) whence;
  192. } */ *uap = v;
  193. struct sys_lseek_args bla;
  194. SCARG(&bla, fd) = SCARG(uap, fd);
  195. SCARG(&bla, offset) = SCARG(uap, offset);
  196. SCARG(&bla, whence) = SCARG(uap, whence);
  197. return sys_lseek(p, &bla, retval);
  198. }
  199. /*
  200. * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
  201. */
  202. int
  203. linux_sys_llseek(p, v, retval)
  204. struct proc *p;
  205. void *v;
  206. register_t *retval;
  207. {
  208. struct linux_sys_llseek_args /* {
  209. syscallarg(int) fd;
  210. syscallarg(uint32_t) ohigh;
  211. syscallarg(uint32_t) olow;
  212. syscallarg(caddr_t) res;
  213. syscallarg(int) whence;
  214. } */ *uap = v;
  215. struct sys_lseek_args bla;
  216. int error;
  217. off_t off;
  218. off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
  219. SCARG(&bla, fd) = SCARG(uap, fd);
  220. SCARG(&bla, offset) = off;
  221. SCARG(&bla, whence) = SCARG(uap, whence);
  222. if ((error = sys_lseek(p, &bla, retval)))
  223. return error;
  224. if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
  225. return error;
  226. retval[0] = 0;
  227. return 0;
  228. }
  229. /*
  230. * The next two functions take care of converting the flock
  231. * structure back and forth between Linux and OpenBSD format.
  232. * The only difference in the structures is the order of
  233. * the fields, and the 'whence' value.
  234. */
  235. static void
  236. bsd_to_linux_flock(bfp, lfp)
  237. struct flock *bfp;
  238. struct linux_flock *lfp;
  239. {
  240. lfp->l_start = bfp->l_start;
  241. lfp->l_len = bfp->l_len;
  242. lfp->l_pid = bfp->l_pid;
  243. lfp->l_whence = bfp->l_whence;
  244. switch (bfp->l_type) {
  245. case F_RDLCK:
  246. lfp->l_type = LINUX_F_RDLCK;
  247. break;
  248. case F_UNLCK:
  249. lfp->l_type = LINUX_F_UNLCK;
  250. break;
  251. case F_WRLCK:
  252. lfp->l_type = LINUX_F_WRLCK;
  253. break;
  254. }
  255. }
  256. static void
  257. linux_to_bsd_flock(lfp, bfp)
  258. struct linux_flock *lfp;
  259. struct flock *bfp;
  260. {
  261. bfp->l_start = lfp->l_start;
  262. bfp->l_len = lfp->l_len;
  263. bfp->l_pid = lfp->l_pid;
  264. bfp->l_whence = lfp->l_whence;
  265. switch (lfp->l_type) {
  266. case LINUX_F_RDLCK:
  267. bfp->l_type = F_RDLCK;
  268. break;
  269. case LINUX_F_UNLCK:
  270. bfp->l_type = F_UNLCK;
  271. break;
  272. case LINUX_F_WRLCK:
  273. bfp->l_type = F_WRLCK;
  274. break;
  275. }
  276. }
  277. /*
  278. * Most actions in the fcntl() call are straightforward; simply
  279. * pass control to the OpenBSD system call. A few commands need
  280. * conversions after the actual system call has done its work,
  281. * because the flag values and lock structure are different.
  282. */
  283. int
  284. linux_sys_fcntl(p, v, retval)
  285. struct proc *p;
  286. void *v;
  287. register_t *retval;
  288. {
  289. struct linux_sys_fcntl_args /* {
  290. syscallarg(int) fd;
  291. syscallarg(int) cmd;
  292. syscallarg(void *) arg;
  293. } */ *uap = v;
  294. int fd, cmd, error;
  295. intptr_t val;
  296. caddr_t arg, sg;
  297. struct linux_flock lfl;
  298. struct flock *bfp, bfl;
  299. struct sys_fcntl_args fca;
  300. struct filedesc *fdp;
  301. struct file *fp;
  302. struct vnode *vp;
  303. struct vattr va;
  304. long pgid;
  305. struct pgrp *pgrp;
  306. struct tty *tp, *(*d_tty)(dev_t);
  307. fd = SCARG(uap, fd);
  308. cmd = SCARG(uap, cmd);
  309. arg = (caddr_t) SCARG(uap, arg);
  310. switch (cmd) {
  311. case LINUX_F_DUPFD:
  312. cmd = F_DUPFD;
  313. break;
  314. case LINUX_F_GETFD:
  315. cmd = F_GETFD;
  316. break;
  317. case LINUX_F_SETFD:
  318. cmd = F_SETFD;
  319. break;
  320. case LINUX_F_GETFL:
  321. SCARG(&fca, fd) = fd;
  322. SCARG(&fca, cmd) = F_GETFL;
  323. SCARG(&fca, arg) = arg;
  324. if ((error = sys_fcntl(p, &fca, retval)))
  325. return error;
  326. retval[0] = bsd_to_linux_ioflags(retval[0]);
  327. return 0;
  328. case LINUX_F_SETFL:
  329. val = linux_to_bsd_ioflags((intptr_t)SCARG(uap, arg));
  330. SCARG(&fca, fd) = fd;
  331. SCARG(&fca, cmd) = F_SETFL;
  332. SCARG(&fca, arg) = (caddr_t) val;
  333. return sys_fcntl(p, &fca, retval);
  334. case LINUX_F_GETLK:
  335. sg = stackgap_init(p);
  336. if ((error = copyin(arg, &lfl, sizeof lfl)))
  337. return error;
  338. linux_to_bsd_flock(&lfl, &bfl);
  339. bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
  340. SCARG(&fca, fd) = fd;
  341. SCARG(&fca, cmd) = F_GETLK;
  342. SCARG(&fca, arg) = bfp;
  343. if ((error = copyout(&bfl, bfp, sizeof bfl)))
  344. return error;
  345. if ((error = sys_fcntl(p, &fca, retval)))
  346. return error;
  347. if ((error = copyin(bfp, &bfl, sizeof bfl)))
  348. return error;
  349. bsd_to_linux_flock(&bfl, &lfl);
  350. error = copyout(&lfl, arg, sizeof lfl);
  351. return error;
  352. break;
  353. case LINUX_F_SETLK:
  354. case LINUX_F_SETLKW:
  355. cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
  356. if ((error = copyin(arg, &lfl, sizeof lfl)))
  357. return error;
  358. linux_to_bsd_flock(&lfl, &bfl);
  359. sg = stackgap_init(p);
  360. bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
  361. if ((error = copyout(&bfl, bfp, sizeof bfl)))
  362. return error;
  363. SCARG(&fca, fd) = fd;
  364. SCARG(&fca, cmd) = cmd;
  365. SCARG(&fca, arg) = bfp;
  366. return sys_fcntl(p, &fca, retval);
  367. break;
  368. case LINUX_F_SETOWN:
  369. case LINUX_F_GETOWN:
  370. /*
  371. * We need to route around the normal fcntl() for these calls,
  372. * since it uses TIOC{G,S}PGRP, which is too restrictive for
  373. * Linux F_{G,S}ETOWN semantics. For sockets, this problem
  374. * does not exist.
  375. */
  376. fdp = p->p_fd;
  377. if ((fp = fd_getfile(fdp, fd)) == NULL)
  378. return (EBADF);
  379. if (fp->f_type == DTYPE_SOCKET) {
  380. cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
  381. break;
  382. }
  383. vp = (struct vnode *)fp->f_data;
  384. if (vp->v_type != VCHR)
  385. return EINVAL;
  386. FREF(fp);
  387. error = VOP_GETATTR(vp, &va, p->p_ucred, p);
  388. FRELE(fp, p);
  389. if (error)
  390. return error;
  391. d_tty = cdevsw[major(va.va_rdev)].d_tty;
  392. if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
  393. return EINVAL;
  394. if (cmd == LINUX_F_GETOWN) {
  395. retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
  396. return 0;
  397. }
  398. if ((long)arg <= 0) {
  399. pgid = -(long)arg;
  400. } else {
  401. struct process *pr = prfind((long)arg);
  402. if (pr == 0)
  403. return (ESRCH);
  404. pgid = (long)pr->ps_pgrp->pg_id;
  405. }
  406. pgrp = pgfind(pgid);
  407. if (pgrp == NULL || pgrp->pg_session != p->p_p->ps_session)
  408. return EPERM;
  409. tp->t_pgrp = pgrp;
  410. return 0;
  411. default:
  412. return EOPNOTSUPP;
  413. }
  414. SCARG(&fca, fd) = fd;
  415. SCARG(&fca, cmd) = cmd;
  416. SCARG(&fca, arg) = arg;
  417. return sys_fcntl(p, &fca, retval);
  418. }
  419. /*
  420. * Convert a OpenBSD stat structure to a Linux stat structure.
  421. * Only the order of the fields and the padding in the structure
  422. * is different. linux_fakedev is a machine-dependent function
  423. * which optionally converts device driver major/minor numbers
  424. * (XXX horrible, but what can you do against code that compares
  425. * things against constant major device numbers? sigh)
  426. */
  427. static int
  428. bsd_to_linux_stat(bsp, lsp)
  429. struct stat *bsp;
  430. struct linux_stat *lsp;
  431. {
  432. if (bsp->st_ino > LINUX_INO_MAX)
  433. return EOVERFLOW;
  434. lsp->lst_dev = bsp->st_dev;
  435. lsp->lst_ino = (linux_ino_t)bsp->st_ino;
  436. lsp->lst_mode = bsp->st_mode;
  437. lsp->lst_nlink = bsp->st_nlink;
  438. lsp->lst_uid = bsp->st_uid;
  439. lsp->lst_gid = bsp->st_gid;
  440. lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
  441. lsp->lst_size = bsp->st_size;
  442. lsp->lst_blksize = bsp->st_blksize;
  443. lsp->lst_blocks = bsp->st_blocks;
  444. lsp->lst_atime = bsp->st_atime;
  445. lsp->lst_mtime = bsp->st_mtime;
  446. lsp->lst_ctime = bsp->st_ctime;
  447. return 0;
  448. }
  449. /*
  450. * The stat functions below are plain sailing. stat and lstat are handled
  451. * by one function to avoid code duplication.
  452. */
  453. int
  454. linux_sys_fstat(p, v, retval)
  455. struct proc *p;
  456. void *v;
  457. register_t *retval;
  458. {
  459. struct linux_sys_fstat_args /* {
  460. syscallarg(int) fd;
  461. syscallarg(linux_stat *) sp;
  462. } */ *uap = v;
  463. struct sys_fstat_args fsa;
  464. struct linux_stat tmplst;
  465. struct stat *st,tmpst;
  466. caddr_t sg;
  467. int error;
  468. sg = stackgap_init(p);
  469. st = stackgap_alloc(&sg, sizeof (struct stat));
  470. SCARG(&fsa, fd) = SCARG(uap, fd);
  471. SCARG(&fsa, sb) = st;
  472. if ((error = sys_fstat(p, &fsa, retval)))
  473. return error;
  474. if ((error = copyin(st, &tmpst, sizeof tmpst)))
  475. return error;
  476. if ((error = bsd_to_linux_stat(&tmpst, &tmplst)))
  477. return error;
  478. if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  479. return error;
  480. return 0;
  481. }
  482. static int
  483. linux_stat1(p, v, retval, dolstat)
  484. struct proc *p;
  485. void *v;
  486. register_t *retval;
  487. int dolstat;
  488. {
  489. struct sys_stat_args sa;
  490. struct linux_stat tmplst;
  491. struct stat *st, tmpst;
  492. caddr_t sg;
  493. int error;
  494. struct linux_sys_stat_args *uap = v;
  495. sg = stackgap_init(p);
  496. st = stackgap_alloc(&sg, sizeof (struct stat));
  497. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  498. SCARG(&sa, ub) = st;
  499. SCARG(&sa, path) = SCARG(uap, path);
  500. if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
  501. sys_stat(p, &sa, retval))))
  502. return error;
  503. if ((error = copyin(st, &tmpst, sizeof tmpst)))
  504. return error;
  505. if ((error = bsd_to_linux_stat(&tmpst, &tmplst)))
  506. return error;
  507. if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  508. return error;
  509. return 0;
  510. }
  511. int
  512. linux_sys_stat(p, v, retval)
  513. struct proc *p;
  514. void *v;
  515. register_t *retval;
  516. {
  517. struct linux_sys_stat_args /* {
  518. syscallarg(char *) path;
  519. syscallarg(struct linux_stat *) sp;
  520. } */ *uap = v;
  521. return linux_stat1(p, uap, retval, 0);
  522. }
  523. int
  524. linux_sys_lstat(p, v, retval)
  525. struct proc *p;
  526. void *v;
  527. register_t *retval;
  528. {
  529. struct linux_sys_lstat_args /* {
  530. syscallarg(char *) path;
  531. syscallarg(struct linux_stat *) sp;
  532. } */ *uap = v;
  533. return linux_stat1(p, uap, retval, 1);
  534. }
  535. /*
  536. * The following syscalls are mostly here because of the alternate path check.
  537. */
  538. int
  539. linux_sys_access(p, v, retval)
  540. struct proc *p;
  541. void *v;
  542. register_t *retval;
  543. {
  544. struct linux_sys_access_args /* {
  545. syscallarg(char *) path;
  546. syscallarg(int) flags;
  547. } */ *uap = v;
  548. caddr_t sg = stackgap_init(p);
  549. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  550. return sys_access(p, uap, retval);
  551. }
  552. int
  553. linux_sys_unlink(p, v, retval)
  554. struct proc *p;
  555. void *v;
  556. register_t *retval;
  557. {
  558. struct linux_sys_unlink_args /* {
  559. syscallarg(char *) path;
  560. } */ *uap = v;
  561. caddr_t sg = stackgap_init(p);
  562. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  563. return sys_unlink(p, uap, retval);
  564. }
  565. int
  566. linux_sys_chdir(p, v, retval)
  567. struct proc *p;
  568. void *v;
  569. register_t *retval;
  570. {
  571. struct linux_sys_chdir_args /* {
  572. syscallarg(char *) path;
  573. } */ *uap = v;
  574. caddr_t sg = stackgap_init(p);
  575. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  576. return sys_chdir(p, uap, retval);
  577. }
  578. int
  579. linux_sys_mknod(p, v, retval)
  580. struct proc *p;
  581. void *v;
  582. register_t *retval;
  583. {
  584. struct linux_sys_mknod_args /* {
  585. syscallarg(char *) path;
  586. syscallarg(int) mode;
  587. syscallarg(int) dev;
  588. } */ *uap = v;
  589. caddr_t sg = stackgap_init(p);
  590. struct sys_mkfifo_args bma;
  591. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  592. /*
  593. * BSD handles FIFOs separately
  594. */
  595. if (S_ISFIFO(SCARG(uap, mode))) {
  596. SCARG(&bma, path) = SCARG(uap, path);
  597. SCARG(&bma, mode) = SCARG(uap, mode);
  598. return sys_mkfifo(p, uap, retval);
  599. } else
  600. return sys_mknod(p, uap, retval);
  601. }
  602. int
  603. linux_sys_chmod(p, v, retval)
  604. struct proc *p;
  605. void *v;
  606. register_t *retval;
  607. {
  608. struct linux_sys_chmod_args /* {
  609. syscallarg(char *) path;
  610. syscallarg(int) mode;
  611. } */ *uap = v;
  612. caddr_t sg = stackgap_init(p);
  613. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  614. return sys_chmod(p, uap, retval);
  615. }
  616. int
  617. linux_sys_chown(struct proc *p, void *v, register_t *retval)
  618. {
  619. struct linux_sys_chown_args /* {
  620. syscallarg(char *) path;
  621. syscallarg(uid_t) uid;
  622. syscallarg(gid_t) gid;
  623. } */ *uap = v;
  624. caddr_t sg = stackgap_init(p);
  625. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  626. return sys_chown(p, uap, retval);
  627. }
  628. int
  629. linux_sys_chown16(p, v, retval)
  630. struct proc *p;
  631. void *v;
  632. register_t *retval;
  633. {
  634. struct linux_sys_chown16_args /* {
  635. syscallarg(char *) path;
  636. syscallarg(int) uid;
  637. syscallarg(int) gid;
  638. } */ *uap = v;
  639. struct sys_chown_args bca;
  640. caddr_t sg = stackgap_init(p);
  641. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  642. SCARG(&bca, path) = SCARG(uap, path);
  643. SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  644. (uid_t)-1 : SCARG(uap, uid);
  645. SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  646. (gid_t)-1 : SCARG(uap, gid);
  647. return sys_chown(p, &bca, retval);
  648. }
  649. int
  650. linux_sys_fchown16(p, v, retval)
  651. struct proc *p;
  652. void *v;
  653. register_t *retval;
  654. {
  655. struct linux_sys_fchown16_args /* {
  656. syscallarg(int) fd;
  657. syscallarg(int) uid;
  658. syscallarg(int) gid;
  659. } */ *uap = v;
  660. struct sys_fchown_args bfa;
  661. SCARG(&bfa, fd) = SCARG(uap, fd);
  662. SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  663. (uid_t)-1 : SCARG(uap, uid);
  664. SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  665. (gid_t)-1 : SCARG(uap, gid);
  666. return sys_fchown(p, &bfa, retval);
  667. }
  668. int
  669. linux_sys_lchown16(p, v, retval)
  670. struct proc *p;
  671. void *v;
  672. register_t *retval;
  673. {
  674. struct linux_sys_lchown16_args /* {
  675. syscallarg(char *) path;
  676. syscallarg(int) uid;
  677. syscallarg(int) gid;
  678. } */ *uap = v;
  679. struct sys_lchown_args bla;
  680. SCARG(&bla, path) = SCARG(uap, path);
  681. SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  682. (uid_t)-1 : SCARG(uap, uid);
  683. SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  684. (gid_t)-1 : SCARG(uap, gid);
  685. return sys_lchown(p, &bla, retval);
  686. }
  687. int
  688. linux_sys_rename(p, v, retval)
  689. struct proc *p;
  690. void *v;
  691. register_t *retval;
  692. {
  693. struct linux_sys_rename_args /* {
  694. syscallarg(char *) from;
  695. syscallarg(char *) to;
  696. } */ *uap = v;
  697. caddr_t sg = stackgap_init(p);
  698. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
  699. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  700. return sys_rename(p, uap, retval);
  701. }
  702. int
  703. linux_sys_mkdir(p, v, retval)
  704. struct proc *p;
  705. void *v;
  706. register_t *retval;
  707. {
  708. struct linux_sys_mkdir_args /* {
  709. syscallarg(char *) path;
  710. syscallarg(int) mode;
  711. } */ *uap = v;
  712. caddr_t sg = stackgap_init(p);
  713. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  714. return sys_mkdir(p, uap, retval);
  715. }
  716. int
  717. linux_sys_rmdir(p, v, retval)
  718. struct proc *p;
  719. void *v;
  720. register_t *retval;
  721. {
  722. struct linux_sys_rmdir_args /* {
  723. syscallarg(char *) path;
  724. } */ *uap = v;
  725. caddr_t sg = stackgap_init(p);
  726. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  727. return sys_rmdir(p, uap, retval);
  728. }
  729. int
  730. linux_sys_symlink(p, v, retval)
  731. struct proc *p;
  732. void *v;
  733. register_t *retval;
  734. {
  735. struct linux_sys_symlink_args /* {
  736. syscallarg(char *) path;
  737. syscallarg(char *) to;
  738. } */ *uap = v;
  739. caddr_t sg = stackgap_init(p);
  740. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  741. LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  742. return sys_symlink(p, uap, retval);
  743. }
  744. int
  745. linux_sys_readlink(p, v, retval)
  746. struct proc *p;
  747. void *v;
  748. register_t *retval;
  749. {
  750. struct linux_sys_readlink_args /* {
  751. syscallarg(char *) name;
  752. syscallarg(char *) buf;
  753. syscallarg(int) count;
  754. } */ *uap = v;
  755. caddr_t sg = stackgap_init(p);
  756. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
  757. return sys_readlink(p, uap, retval);
  758. }
  759. int
  760. linux_sys_ftruncate(p, v, retval)
  761. struct proc *p;
  762. void *v;
  763. register_t *retval;
  764. {
  765. struct linux_sys_ftruncate_args /* {
  766. syscallarg(int) fd;
  767. syscallarg(long) length;
  768. } */ *uap = v;
  769. struct sys_ftruncate_args sta;
  770. SCARG(&sta, fd) = SCARG(uap, fd);
  771. SCARG(&sta, length) = SCARG(uap, length);
  772. return sys_ftruncate(p, uap, retval);
  773. }
  774. int
  775. linux_sys_truncate(p, v, retval)
  776. struct proc *p;
  777. void *v;
  778. register_t *retval;
  779. {
  780. struct linux_sys_truncate_args /* {
  781. syscallarg(char *) path;
  782. syscallarg(long) length;
  783. } */ *uap = v;
  784. caddr_t sg = stackgap_init(p);
  785. struct sys_truncate_args sta;
  786. LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  787. SCARG(&sta, path) = SCARG(uap, path);
  788. SCARG(&sta, length) = SCARG(uap, length);
  789. return sys_truncate(p, &sta, retval);
  790. }
  791. /*
  792. * This is just fsync() for now (just as it is in the Linux kernel)
  793. */
  794. int
  795. linux_sys_fdatasync(p, v, retval)
  796. struct proc *p;
  797. void *v;
  798. register_t *retval;
  799. {
  800. struct linux_sys_fdatasync_args /* {
  801. syscallarg(int) fd;
  802. } */ *uap = v;
  803. return sys_fsync(p, uap, retval);
  804. }
  805. /*
  806. * pread(2).
  807. */
  808. int
  809. linux_sys_pread(p, v, retval)
  810. struct proc *p;
  811. void *v;
  812. register_t *retval;
  813. {
  814. struct linux_sys_pread_args /* {
  815. syscallarg(int) fd;
  816. syscallarg(void *) buf;
  817. syscallarg(size_t) nbyte;
  818. syscallarg(linux_off_t) offset;
  819. } */ *uap = v;
  820. struct sys_pread_args pra;
  821. SCARG(&pra, fd) = SCARG(uap, fd);
  822. SCARG(&pra, buf) = SCARG(uap, buf);
  823. SCARG(&pra, nbyte) = SCARG(uap, nbyte);
  824. SCARG(&pra, offset) = SCARG(uap, offset);
  825. return sys_pread(p, &pra, retval);
  826. }
  827. /*
  828. * pwrite(2).
  829. */
  830. int
  831. linux_sys_pwrite(p, v, retval)
  832. struct proc *p;
  833. void *v;
  834. register_t *retval;
  835. {
  836. struct linux_sys_pwrite_args /* {
  837. syscallarg(int) fd;
  838. syscallarg(char *) buf;
  839. syscallarg(size_t) nbyte;
  840. syscallarg(linux_off_t) offset;
  841. } */ *uap = v;
  842. struct sys_pwrite_args pra;
  843. SCARG(&pra, fd) = SCARG(uap, fd);
  844. SCARG(&pra, buf) = SCARG(uap, buf);
  845. SCARG(&pra, nbyte) = SCARG(uap, nbyte);
  846. SCARG(&pra, offset) = SCARG(uap, offset);
  847. return sys_pwrite(p, &pra, retval);
  848. }