fs.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:20k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: fs.c,v 1.25 2001/09/19 00:04:30 davem Exp $
  2.  * fs.c: fs related syscall emulation for Solaris
  3.  *
  4.  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5.  *
  6.  * 1999-08-19 Implemented solaris F_FREESP (truncate)
  7.  *            fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu)
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/sched.h>
  11. #include <linux/slab.h>
  12. #include <linux/fs.h>
  13. #include <linux/mm.h>
  14. #include <linux/file.h>
  15. #include <linux/stat.h>
  16. #include <linux/smp_lock.h>
  17. #include <linux/limits.h>
  18. #include <linux/resource.h>
  19. #include <linux/quotaops.h>
  20. #include <asm/uaccess.h>
  21. #include <asm/string.h>
  22. #include <asm/ptrace.h>
  23. #include "conv.h"
  24. #define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10))
  25. #define R4_MAJOR(DEV) (((DEV) >> 18) & 0x3fff)
  26. #define R4_MINOR(DEV) ((DEV) & 0x3ffff)
  27. #define R3_VERSION 1
  28. #define R4_VERSION 2
  29. typedef struct {
  30. s32 tv_sec;
  31. s32 tv_nsec;
  32. } timestruct_t;
  33. struct sol_stat {
  34. u32 st_dev;
  35. s32 st_pad1[3];     /* network id */
  36. u32 st_ino;
  37. u32 st_mode;
  38. u32 st_nlink;
  39. u32 st_uid;
  40. u32 st_gid;
  41. u32 st_rdev;
  42. s32 st_pad2[2];
  43. s32 st_size;
  44. s32 st_pad3; /* st_size, off_t expansion */
  45. timestruct_t st_atime;
  46. timestruct_t st_mtime;
  47. timestruct_t st_ctime;
  48. s32 st_blksize;
  49. s32 st_blocks;
  50. char st_fstype[16];
  51. s32 st_pad4[8];     /* expansion area */
  52. };
  53. struct sol_stat64 {
  54. u32 st_dev;
  55. s32 st_pad1[3];     /* network id */
  56. u64 st_ino;
  57. u32 st_mode;
  58. u32 st_nlink;
  59. u32 st_uid;
  60. u32 st_gid;
  61. u32 st_rdev;
  62. s32 st_pad2[2];
  63. s64 st_size;
  64. timestruct_t st_atime;
  65. timestruct_t st_mtime;
  66. timestruct_t st_ctime;
  67. s64 st_blksize;
  68. s32 st_blocks;
  69. char st_fstype[16];
  70. s32 st_pad4[4];     /* expansion area */
  71. };
  72. #define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
  73. static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
  74. {
  75. if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev) ||
  76.     __put_user (kbuf->st_ino, &ubuf->st_ino) ||
  77.     __put_user (kbuf->st_mode, &ubuf->st_mode) ||
  78.     __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
  79.     __put_user (kbuf->st_uid, &ubuf->st_uid) ||
  80.     __put_user (kbuf->st_gid, &ubuf->st_gid) ||
  81.     __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev) ||
  82.     __put_user (kbuf->st_size, &ubuf->st_size) ||
  83.     __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
  84.     __put_user (0, &ubuf->st_atime.tv_nsec) ||
  85.     __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
  86.     __put_user (0, &ubuf->st_mtime.tv_nsec) ||
  87.     __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
  88.     __put_user (0, &ubuf->st_ctime.tv_nsec) ||
  89.     __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
  90.     __put_user (kbuf->st_blocks, &ubuf->st_blocks) ||
  91.     __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
  92. return -EFAULT;
  93. return 0;
  94. }
  95. static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
  96. {
  97. if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev) ||
  98.     __put_user (kbuf->st_ino, &ubuf->st_ino) ||
  99.     __put_user (kbuf->st_mode, &ubuf->st_mode) ||
  100.     __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
  101.     __put_user (kbuf->st_uid, &ubuf->st_uid) ||
  102.     __put_user (kbuf->st_gid, &ubuf->st_gid) ||
  103.     __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev) ||
  104.     __put_user (kbuf->st_size, &ubuf->st_size) ||
  105.     __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
  106.     __put_user (0, &ubuf->st_atime.tv_nsec) ||
  107.     __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
  108.     __put_user (0, &ubuf->st_mtime.tv_nsec) ||
  109.     __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
  110.     __put_user (0, &ubuf->st_ctime.tv_nsec) ||
  111.     __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
  112.     __put_user (kbuf->st_blocks, &ubuf->st_blocks) ||
  113.     __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
  114. return -EFAULT;
  115. return 0;
  116. }
  117. asmlinkage int solaris_stat(u32 filename, u32 statbuf)
  118. {
  119. int ret;
  120. struct stat s;
  121. char *filenam;
  122. mm_segment_t old_fs = get_fs();
  123. int (*sys_newstat)(char *,struct stat *) = 
  124. (int (*)(char *,struct stat *))SYS(stat);
  125. filenam = getname ((char *)A(filename));
  126. ret = PTR_ERR(filenam);
  127. if (!IS_ERR(filenam)) {
  128. set_fs (KERNEL_DS);
  129. ret = sys_newstat(filenam, &s);
  130. set_fs (old_fs);
  131. putname (filenam);
  132. if (putstat ((struct sol_stat *)A(statbuf), &s))
  133. return -EFAULT;
  134. }
  135. return ret;
  136. }
  137. asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
  138. {
  139. /* Solaris doesn't bother with looking at vers, so we do neither */
  140. return solaris_stat(filename, statbuf);
  141. }
  142. asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
  143. {
  144. int ret;
  145. struct stat s;
  146. char *filenam;
  147. mm_segment_t old_fs = get_fs();
  148. int (*sys_newstat)(char *,struct stat *) = 
  149. (int (*)(char *,struct stat *))SYS(stat);
  150. filenam = getname ((char *)A(filename));
  151. ret = PTR_ERR(filenam);
  152. if (!IS_ERR(filenam)) {
  153. set_fs (KERNEL_DS);
  154. ret = sys_newstat(filenam, &s);
  155. set_fs (old_fs);
  156. putname (filenam);
  157. if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
  158. return -EFAULT;
  159. }
  160. return ret;
  161. }
  162. asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
  163. {
  164. int ret;
  165. struct stat s;
  166. char *filenam;
  167. mm_segment_t old_fs = get_fs();
  168. int (*sys_newlstat)(char *,struct stat *) = 
  169. (int (*)(char *,struct stat *))SYS(lstat);
  170. filenam = getname ((char *)A(filename));
  171. ret = PTR_ERR(filenam);
  172. if (!IS_ERR(filenam)) {
  173. set_fs (KERNEL_DS);
  174. ret = sys_newlstat(filenam, &s);
  175. set_fs (old_fs);
  176. putname (filenam);
  177. if (putstat ((struct sol_stat *)A(statbuf), &s))
  178. return -EFAULT;
  179. }
  180. return ret;
  181. }
  182. asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
  183. {
  184. return solaris_lstat(filename, statbuf);
  185. }
  186. asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
  187. {
  188. int ret;
  189. struct stat s;
  190. char *filenam;
  191. mm_segment_t old_fs = get_fs();
  192. int (*sys_newlstat)(char *,struct stat *) = 
  193. (int (*)(char *,struct stat *))SYS(lstat);
  194. filenam = getname ((char *)A(filename));
  195. ret = PTR_ERR(filenam);
  196. if (!IS_ERR(filenam)) {
  197. set_fs (KERNEL_DS);
  198. ret = sys_newlstat(filenam, &s);
  199. set_fs (old_fs);
  200. putname (filenam);
  201. if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
  202. return -EFAULT;
  203. }
  204. return ret;
  205. }
  206. asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
  207. {
  208. int ret;
  209. struct stat s;
  210. mm_segment_t old_fs = get_fs();
  211. int (*sys_newfstat)(unsigned,struct stat *) = 
  212. (int (*)(unsigned,struct stat *))SYS(fstat);
  213. set_fs (KERNEL_DS);
  214. ret = sys_newfstat(fd, &s);
  215. set_fs (old_fs);
  216. if (putstat ((struct sol_stat *)A(statbuf), &s))
  217. return -EFAULT;
  218. return ret;
  219. }
  220. asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
  221. {
  222. return solaris_fstat(fd, statbuf);
  223. }
  224. asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
  225. {
  226. int ret;
  227. struct stat s;
  228. mm_segment_t old_fs = get_fs();
  229. int (*sys_newfstat)(unsigned,struct stat *) = 
  230. (int (*)(unsigned,struct stat *))SYS(fstat);
  231. set_fs (KERNEL_DS);
  232. ret = sys_newfstat(fd, &s);
  233. set_fs (old_fs);
  234. if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
  235. return -EFAULT;
  236. return ret;
  237. }
  238. asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
  239. {
  240. int (*sys_mknod)(const char *,int,dev_t) = 
  241. (int (*)(const char *,int,dev_t))SYS(mknod);
  242. int major, minor;
  243. if ((major = R4_MAJOR(dev)) > 255 || 
  244.     (minor = R4_MINOR(dev)) > 255) return -EINVAL;
  245. return sys_mknod((const char *)A(path), mode, MKDEV(major,minor));
  246. }
  247. asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
  248. {
  249. return solaris_mknod(path, mode, dev);
  250. }
  251. asmlinkage int solaris_getdents64(unsigned int fd, void *dirent, unsigned int count)
  252. {
  253. int (*sys_getdents)(unsigned int, void *, unsigned int) =
  254. (int (*)(unsigned int, void *, unsigned int))SYS(getdents);
  255. return sys_getdents(fd, dirent, count);
  256. }
  257. /* This statfs thingie probably will go in the near future, but... */
  258. struct sol_statfs {
  259. short f_type;
  260. s32 f_bsize;
  261. s32 f_frsize;
  262. s32 f_blocks;
  263. s32 f_bfree;
  264. u32 f_files;
  265. u32 f_ffree;
  266. char f_fname[6];
  267. char f_fpack[6];
  268. };
  269. asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype)
  270. {
  271. int ret;
  272. struct statfs s;
  273. mm_segment_t old_fs = get_fs();
  274. int (*sys_statfs)(const char *,struct statfs *) = 
  275. (int (*)(const char *,struct statfs *))SYS(statfs);
  276. struct sol_statfs *ss = (struct sol_statfs *)A(buf);
  277. if (len != sizeof(struct sol_statfs)) return -EINVAL;
  278. if (!fstype) {
  279. set_fs (KERNEL_DS);
  280. ret = sys_statfs((const char *)A(path), &s);
  281. set_fs (old_fs);
  282. if (!ret) {
  283. if (put_user (s.f_type, &ss->f_type) ||
  284.     __put_user (s.f_bsize, &ss->f_bsize) ||
  285.     __put_user (0, &ss->f_frsize) ||
  286.     __put_user (s.f_blocks, &ss->f_blocks) ||
  287.     __put_user (s.f_bfree, &ss->f_bfree) ||
  288.     __put_user (s.f_files, &ss->f_files) ||
  289.     __put_user (s.f_ffree, &ss->f_ffree) ||
  290.     __clear_user (&ss->f_fname, 12))
  291. return -EFAULT;
  292. }
  293. return ret;
  294. }
  295. /* Linux can't stat unmounted filesystems so we
  296.  * simply lie and claim 100MB of 1GB is free. Sorry.
  297.  */
  298. if (put_user (fstype, &ss->f_type) ||
  299.     __put_user (1024, &ss->f_bsize) ||
  300.     __put_user (0, &ss->f_frsize) ||
  301.     __put_user (1024*1024, &ss->f_blocks) ||
  302.     __put_user (100*1024, &ss->f_bfree) ||
  303.     __put_user (60000, &ss->f_files) ||
  304.     __put_user (50000, &ss->f_ffree) ||
  305.     __clear_user (&ss->f_fname, 12))
  306. return -EFAULT;
  307. return 0;
  308. }
  309. asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype)
  310. {
  311. int ret;
  312. struct statfs s;
  313. mm_segment_t old_fs = get_fs();
  314. int (*sys_fstatfs)(unsigned,struct statfs *) = 
  315. (int (*)(unsigned,struct statfs *))SYS(fstatfs);
  316. struct sol_statfs *ss = (struct sol_statfs *)A(buf);
  317. if (len != sizeof(struct sol_statfs)) return -EINVAL;
  318. if (!fstype) {
  319. set_fs (KERNEL_DS);
  320. ret = sys_fstatfs(fd, &s);
  321. set_fs (old_fs);
  322. if (!ret) {
  323. if (put_user (s.f_type, &ss->f_type) ||
  324.     __put_user (s.f_bsize, &ss->f_bsize) ||
  325.     __put_user (0, &ss->f_frsize) ||
  326.     __put_user (s.f_blocks, &ss->f_blocks) ||
  327.     __put_user (s.f_bfree, &ss->f_bfree) ||
  328.     __put_user (s.f_files, &ss->f_files) ||
  329.     __put_user (s.f_ffree, &ss->f_ffree) ||
  330.     __clear_user (&ss->f_fname, 12))
  331. return -EFAULT;
  332. }
  333. return ret;
  334. }
  335. /* Otherwise fstatfs is the same as statfs */
  336. return solaris_statfs(0, buf, len, fstype);
  337. }
  338. struct sol_statvfs {
  339. u32 f_bsize;
  340. u32 f_frsize;
  341. u32 f_blocks;
  342. u32 f_bfree;
  343. u32 f_bavail;
  344. u32 f_files;
  345. u32 f_ffree;
  346. u32 f_favail;
  347. u32 f_fsid;
  348. char f_basetype[16];
  349. u32 f_flag;
  350. u32 f_namemax;
  351. char f_fstr[32];
  352. u32 f_filler[16];
  353. };
  354. struct sol_statvfs64 {
  355. u32 f_bsize;
  356. u32 f_frsize;
  357. u64 f_blocks;
  358. u64 f_bfree;
  359. u64 f_bavail;
  360. u64 f_files;
  361. u64 f_ffree;
  362. u64 f_favail;
  363. u32 f_fsid;
  364. char f_basetype[16];
  365. u32 f_flag;
  366. u32 f_namemax;
  367. char f_fstr[32];
  368. u32 f_filler[16];
  369. };
  370. static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
  371. {
  372. struct statfs s;
  373. int error;
  374. struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
  375. error = vfs_statfs(mnt->mnt_sb, &s);
  376. if (!error) {
  377. const char *p = mnt->mnt_sb->s_type->name;
  378. int i = 0;
  379. int j = strlen (p);
  380. if (j > 15) j = 15;
  381. if (IS_RDONLY(inode)) i = 1;
  382. if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
  383. if (put_user (s.f_bsize, &ss->f_bsize) ||
  384.     __put_user (0, &ss->f_frsize) ||
  385.     __put_user (s.f_blocks, &ss->f_blocks) ||
  386.     __put_user (s.f_bfree, &ss->f_bfree) ||
  387.     __put_user (s.f_bavail, &ss->f_bavail) ||
  388.     __put_user (s.f_files, &ss->f_files) ||
  389.     __put_user (s.f_ffree, &ss->f_ffree) ||
  390.     __put_user (s.f_ffree, &ss->f_favail) ||
  391.     __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
  392.     __copy_to_user (ss->f_basetype,p,j) ||
  393.     __put_user (0, (char *)&ss->f_basetype[j]) ||
  394.     __put_user (s.f_namelen, &ss->f_namemax) ||
  395.     __put_user (i, &ss->f_flag) ||     
  396.     __clear_user (&ss->f_fstr, 32))
  397. return -EFAULT;
  398. }
  399. return error;
  400. }
  401. static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
  402. {
  403. struct statfs s;
  404. int error;
  405. struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
  406. error = vfs_statfs(mnt->mnt_sb, &s);
  407. if (!error) {
  408. const char *p = mnt->mnt_sb->s_type->name;
  409. int i = 0;
  410. int j = strlen (p);
  411. if (j > 15) j = 15;
  412. if (IS_RDONLY(inode)) i = 1;
  413. if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
  414. if (put_user (s.f_bsize, &ss->f_bsize) ||
  415.     __put_user (0, &ss->f_frsize) ||
  416.     __put_user (s.f_blocks, &ss->f_blocks) ||
  417.     __put_user (s.f_bfree, &ss->f_bfree) ||
  418.     __put_user (s.f_bavail, &ss->f_bavail) ||
  419.     __put_user (s.f_files, &ss->f_files) ||
  420.     __put_user (s.f_ffree, &ss->f_ffree) ||
  421.     __put_user (s.f_ffree, &ss->f_favail) ||
  422.     __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
  423.     __copy_to_user (ss->f_basetype,p,j) ||
  424.     __put_user (0, (char *)&ss->f_basetype[j]) ||
  425.     __put_user (s.f_namelen, &ss->f_namemax) ||
  426.     __put_user (i, &ss->f_flag) ||     
  427.     __clear_user (&ss->f_fstr, 32))
  428. return -EFAULT;
  429. }
  430. return error;
  431. }
  432. asmlinkage int solaris_statvfs(u32 path, u32 buf)
  433. {
  434. struct nameidata nd;
  435. int error;
  436. error = user_path_walk((const char *)A(path),&nd);
  437. if (!error) {
  438. struct inode * inode = nd.dentry->d_inode;
  439. error = report_statvfs(nd.mnt, inode, buf);
  440. path_release(&nd);
  441. }
  442. return error;
  443. }
  444. asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
  445. {
  446. struct file * file;
  447. int error;
  448. error = -EBADF;
  449. file = fget(fd);
  450. if (file) {
  451. error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf);
  452. fput(file);
  453. }
  454. return error;
  455. }
  456. asmlinkage int solaris_statvfs64(u32 path, u32 buf)
  457. {
  458. struct nameidata nd;
  459. int error;
  460. lock_kernel();
  461. error = user_path_walk((const char *)A(path), &nd);
  462. if (!error) {
  463. struct inode * inode = nd.dentry->d_inode;
  464. error = report_statvfs64(nd.mnt, inode, buf);
  465. path_release(&nd);
  466. }
  467. unlock_kernel();
  468. return error;
  469. }
  470. asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
  471. {
  472. struct file * file;
  473. int error;
  474. error = -EBADF;
  475. file = fget(fd);
  476. if (file) {
  477. lock_kernel();
  478. error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf);
  479. unlock_kernel();
  480. fput(file);
  481. }
  482. return error;
  483. }
  484. extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
  485. asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
  486. {
  487. const char *filename = (const char *)(long)fname;
  488. int fl = flags & 0xf;
  489. /* Translate flags first. */
  490. if (flags & 0x2000) fl |= O_LARGEFILE;
  491. if (flags & 0x8050) fl |= O_SYNC;
  492. if (flags & 0x80) fl |= O_NONBLOCK;
  493. if (flags & 0x100) fl |= O_CREAT;
  494. if (flags & 0x200) fl |= O_TRUNC;
  495. if (flags & 0x400) fl |= O_EXCL;
  496. if (flags & 0x800) fl |= O_NOCTTY;
  497. flags = fl;
  498. return sparc32_open(filename, flags, mode);
  499. }
  500. #define SOL_F_SETLK 6
  501. #define SOL_F_SETLKW 7
  502. #define SOL_F_FREESP    11
  503. #define SOL_F_ISSTREAM  13
  504. #define SOL_F_GETLK     14
  505. #define SOL_F_PRIV      15
  506. #define SOL_F_NPRIV     16
  507. #define SOL_F_QUOTACTL  17
  508. #define SOL_F_BLOCKS    18
  509. #define SOL_F_BLKSIZE   19
  510. #define SOL_F_GETOWN    23
  511. #define SOL_F_SETOWN    24
  512. struct sol_flock {
  513. short l_type;
  514. short l_whence;
  515. u32 l_start;
  516. u32 l_len;
  517. s32 l_sysid;
  518. s32 l_pid;
  519. s32 l_pad[4];
  520. };
  521. asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg)
  522. {
  523. int (*sys_fcntl)(unsigned,unsigned,unsigned long) = 
  524. (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl);
  525. int ret, flags;
  526. switch (cmd) {
  527. case F_DUPFD:
  528. case F_GETFD:
  529. case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg);
  530. case F_GETFL:
  531. flags = sys_fcntl(fd, cmd, 0);
  532. ret = flags & 0xf;
  533. if (flags & O_SYNC) ret |= 0x8050;
  534. if (flags & O_NONBLOCK) ret |= 0x80;
  535. return ret;
  536. case F_SETFL:
  537. flags = arg & 0xf;
  538. if (arg & 0x8050) flags |= O_SYNC;
  539. if (arg & 0x80) flags |= O_NONBLOCK;
  540. return sys_fcntl(fd, cmd, (long)flags);
  541. case SOL_F_GETLK:
  542. case SOL_F_SETLK:
  543. case SOL_F_SETLKW:
  544. {
  545. struct flock f;
  546. mm_segment_t old_fs = get_fs();
  547. switch (cmd) {
  548. case SOL_F_GETLK: cmd = F_GETLK; break;
  549. case SOL_F_SETLK: cmd = F_SETLK; break;
  550. case SOL_F_SETLKW: cmd = F_SETLKW; break;
  551. }
  552. if (get_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
  553.     __get_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
  554.     __get_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
  555.     __get_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
  556.     __get_user (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid))
  557. return -EFAULT;
  558. set_fs(KERNEL_DS);
  559. ret = sys_fcntl(fd, cmd, (unsigned long)&f);
  560. set_fs(old_fs);
  561. if (__put_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
  562.     __put_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
  563.     __put_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
  564.     __put_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
  565.     __put_user (f.l_pid, &((struct sol_flock *)A(arg))->l_pid) ||
  566.     __put_user (0, &((struct sol_flock *)A(arg))->l_sysid))
  567. return -EFAULT;
  568. return ret;
  569. }
  570. case SOL_F_FREESP:
  571.         { 
  572.     int length;
  573.     int (*sys_newftruncate)(unsigned int, unsigned long)=
  574.     (int (*)(unsigned int, unsigned long))SYS(ftruncate);
  575.     if (get_user(length, &((struct sol_flock*)A(arg))->l_start))
  576.     return -EFAULT;
  577.     return sys_newftruncate(fd, length);
  578. }
  579. };
  580. return -EINVAL;
  581. }
  582. asmlinkage int solaris_ulimit(int cmd, int val)
  583. {
  584. switch (cmd) {
  585. case 1: /* UL_GETFSIZE - in 512B chunks */
  586. return current->rlim[RLIMIT_FSIZE].rlim_cur >> 9;
  587. case 2: /* UL_SETFSIZE */
  588. if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE;
  589. val <<= 9;
  590. lock_kernel();
  591. if (val > current->rlim[RLIMIT_FSIZE].rlim_max) {
  592. if (!capable(CAP_SYS_RESOURCE)) {
  593. unlock_kernel();
  594. return -EPERM;
  595. }
  596. current->rlim[RLIMIT_FSIZE].rlim_max = val;
  597. }
  598. current->rlim[RLIMIT_FSIZE].rlim_cur = val;
  599. unlock_kernel();
  600. return 0;
  601. case 3: /* UL_GMEMLIM */
  602. return current->rlim[RLIMIT_DATA].rlim_cur;
  603. case 4: /* UL_GDESLIM */
  604. return NR_OPEN;
  605. }
  606. return -EINVAL;
  607. }
  608. /* At least at the time I'm writing this, Linux doesn't have ACLs, so we
  609.    just fake this */
  610. asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp)
  611. {
  612. return -ENOSYS;
  613. }
  614. asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
  615. {
  616. return -ENOSYS;
  617. }
  618. asmlinkage int solaris_pread(unsigned int fd, char *buf, u32 count, u32 pos)
  619. {
  620. ssize_t (*sys_pread)(unsigned int, char *, size_t, loff_t) =
  621. (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pread);
  622. return sys_pread(fd, buf, count, (loff_t)pos);
  623. }
  624. asmlinkage int solaris_pwrite(unsigned int fd, char *buf, u32 count, u32 pos)
  625. {
  626. ssize_t (*sys_pwrite)(unsigned int, char *, size_t, loff_t) =
  627. (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pwrite);
  628. return sys_pwrite(fd, buf, count, (loff_t)pos);
  629. }
  630. /* POSIX.1 names */
  631. #define _PC_LINK_MAX    1
  632. #define _PC_MAX_CANON   2
  633. #define _PC_MAX_INPUT   3
  634. #define _PC_NAME_MAX    4
  635. #define _PC_PATH_MAX    5
  636. #define _PC_PIPE_BUF    6
  637. #define _PC_NO_TRUNC    7
  638. #define _PC_VDISABLE    8
  639. #define _PC_CHOWN_RESTRICTED    9
  640. /* POSIX.4 names */
  641. #define _PC_ASYNC_IO    10
  642. #define _PC_PRIO_IO     11
  643. #define _PC_SYNC_IO     12
  644. #define _PC_LAST        12
  645. /* This is not a real and complete implementation yet, just to keep
  646.  * the easy Solaris binaries happy.
  647.  */
  648. asmlinkage int solaris_fpathconf(int fd, int name)
  649. {
  650. int ret;
  651. switch(name) {
  652. case _PC_LINK_MAX:
  653. ret = LINK_MAX;
  654. break;
  655. case _PC_MAX_CANON:
  656. ret = MAX_CANON;
  657. break;
  658. case _PC_MAX_INPUT:
  659. ret = MAX_INPUT;
  660. break;
  661. case _PC_NAME_MAX:
  662. ret = NAME_MAX;
  663. break;
  664. case _PC_PATH_MAX:
  665. ret = PATH_MAX;
  666. break;
  667. case _PC_PIPE_BUF:
  668. ret = PIPE_BUF;
  669. break;
  670. case _PC_CHOWN_RESTRICTED:
  671. ret = 1;
  672. break;
  673. case _PC_NO_TRUNC:
  674. case _PC_VDISABLE:
  675. ret = 0;
  676. break;
  677. default:
  678. ret = -EINVAL;
  679. break;
  680. }
  681. return ret;
  682. }
  683. asmlinkage int solaris_pathconf(u32 path, int name)
  684. {
  685. return solaris_fpathconf(0, name);
  686. }
  687. /* solaris_llseek returns long long - quite difficult */
  688. asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence)
  689. {
  690. int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int) =
  691. (int (*)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int))SYS(_llseek);
  692. int ret;
  693. mm_segment_t old_fs = get_fs();
  694. loff_t retval;
  695. set_fs(KERNEL_DS);
  696. ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence);
  697. set_fs(old_fs);
  698. if (ret < 0) return ret;
  699. regs->u_regs[UREG_I1] = (u32)retval;
  700. return (retval >> 32);
  701. }
  702. /* Have to mask out all but lower 3 bits */
  703. asmlinkage int solaris_access(u32 filename, long mode)
  704. {
  705. int (*sys_access)(const char *, int) = 
  706. (int (*)(const char *, int))SYS(access);
  707. return sys_access((const char *)A(filename), mode & 7);
  708. }