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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * file.c
  3.  *
  4.  * PURPOSE
  5.  *  File handling routines for the OSTA-UDF(tm) filesystem.
  6.  *
  7.  * CONTACTS
  8.  *  E-mail regarding any portion of the Linux UDF file system should be
  9.  *  directed to the development team mailing list (run by majordomo):
  10.  *    linux_udf@hpesjro.fc.hp.com
  11.  *
  12.  * COPYRIGHT
  13.  *  This file is distributed under the terms of the GNU General Public
  14.  *  License (GPL). Copies of the GPL can be obtained from:
  15.  *    ftp://prep.ai.mit.edu/pub/gnu/GPL
  16.  *  Each contributing author retains all rights to their own work.
  17.  *
  18.  *  (C) 1998-1999 Dave Boynton
  19.  *  (C) 1998-2000 Ben Fennema
  20.  *  (C) 1999-2000 Stelias Computing Inc
  21.  *
  22.  * HISTORY
  23.  *
  24.  *  10/02/98 dgb  Attempt to integrate into udf.o
  25.  *  10/07/98      Switched to using generic_readpage, etc., like isofs
  26.  *                And it works!
  27.  *  12/06/98 blf  Added udf_file_read. uses generic_file_read for all cases but
  28.  *                ICB_FLAG_AD_IN_ICB.
  29.  *  04/06/99      64 bit file handling on 32 bit systems taken from ext2 file.c
  30.  *  05/12/99      Preliminary file write support
  31.  */
  32. #include "udfdecl.h"
  33. #include <linux/fs.h>
  34. #include <linux/udf_fs.h>
  35. #include <asm/uaccess.h>
  36. #include <linux/kernel.h>
  37. #include <linux/string.h> /* memset */
  38. #include <linux/errno.h>
  39. #include <linux/locks.h>
  40. #include <linux/smp_lock.h>
  41. #include "udf_i.h"
  42. #include "udf_sb.h"
  43. static int udf_adinicb_readpage(struct file *file, struct page * page)
  44. {
  45. struct inode *inode = page->mapping->host;
  46. struct buffer_head *bh;
  47. int block;
  48. char *kaddr;
  49. if (!PageLocked(page))
  50. PAGE_BUG(page);
  51. kaddr = kmap(page);
  52. memset(kaddr, 0, PAGE_CACHE_SIZE);
  53. block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
  54. bh = sb_bread(inode->i_sb, block);
  55. memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
  56. brelse(bh);
  57. flush_dcache_page(page);
  58. SetPageUptodate(page);
  59. kunmap(page);
  60. UnlockPage(page);
  61. return 0;
  62. }
  63. static int udf_adinicb_writepage(struct page *page)
  64. {
  65. struct inode *inode = page->mapping->host;
  66. struct buffer_head *bh;
  67. int block;
  68. char *kaddr;
  69. if (!PageLocked(page))
  70. PAGE_BUG(page);
  71. kaddr = kmap(page);
  72. block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
  73. bh = sb_bread(inode->i_sb, block);
  74. memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
  75. mark_buffer_dirty(bh);
  76. brelse(bh);
  77. SetPageUptodate(page);
  78. kunmap(page);
  79. UnlockPage(page);
  80. return 0;
  81. }
  82. static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  83. {
  84. kmap(page);
  85. return 0;
  86. }
  87. static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  88. {
  89. struct inode *inode = page->mapping->host;
  90. struct buffer_head *bh;
  91. int block;
  92. char *kaddr = page_address(page);
  93. block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
  94. bh = sb_bread(inode->i_sb, block);
  95. memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
  96. kaddr + offset, to-offset);
  97. mark_buffer_dirty(bh);
  98. brelse(bh);
  99. SetPageUptodate(page);
  100. kunmap(page);
  101. /* only one page here */
  102. if (to > inode->i_size)
  103. inode->i_size = to;
  104. return 0;
  105. }
  106. struct address_space_operations udf_adinicb_aops = {
  107. readpage: udf_adinicb_readpage,
  108. writepage: udf_adinicb_writepage,
  109. sync_page: block_sync_page,
  110. prepare_write: udf_adinicb_prepare_write,
  111. commit_write: udf_adinicb_commit_write,
  112. };
  113. static ssize_t udf_file_write(struct file * file, const char * buf,
  114. size_t count, loff_t *ppos)
  115. {
  116. ssize_t retval;
  117. struct inode *inode = file->f_dentry->d_inode;
  118. int err, pos;
  119. if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
  120. {
  121. if (file->f_flags & O_APPEND)
  122. pos = inode->i_size;
  123. else
  124. pos = *ppos;
  125. if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
  126. pos + count))
  127. {
  128. udf_expand_file_adinicb(inode, pos + count, &err);
  129. if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
  130. {
  131. udf_debug("udf_expand_adinicb: err=%dn", err);
  132. return err;
  133. }
  134. }
  135. else
  136. {
  137. if (pos + count > inode->i_size)
  138. UDF_I_LENALLOC(inode) = pos + count;
  139. else
  140. UDF_I_LENALLOC(inode) = inode->i_size;
  141. }
  142. }
  143. retval = generic_file_write(file, buf, count, ppos);
  144. if (retval > 0)
  145. {
  146. UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
  147. mark_inode_dirty(inode);
  148. }
  149. return retval;
  150. }
  151. /*
  152.  * udf_ioctl
  153.  *
  154.  * PURPOSE
  155.  * Issue an ioctl.
  156.  *
  157.  * DESCRIPTION
  158.  * Optional - sys_ioctl() will return -ENOTTY if this routine is not
  159.  * available, and the ioctl cannot be handled without filesystem help.
  160.  *
  161.  * sys_ioctl() handles these ioctls that apply only to regular files:
  162.  * FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
  163.  * These ioctls are also handled by sys_ioctl():
  164.  * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
  165.  * All other ioctls are passed to the filesystem.
  166.  *
  167.  * Refer to sys_ioctl() in fs/ioctl.c
  168.  * sys_ioctl() -> .
  169.  *
  170.  * PRE-CONDITIONS
  171.  * inode Pointer to inode that ioctl was issued on.
  172.  * filp Pointer to file that ioctl was issued on.
  173.  * cmd The ioctl command.
  174.  * arg The ioctl argument [can be interpreted as a
  175.  * user-space pointer if desired].
  176.  *
  177.  * POST-CONDITIONS
  178.  * <return> Success (>=0) or an error code (<=0) that
  179.  * sys_ioctl() will return.
  180.  *
  181.  * HISTORY
  182.  * July 1, 1997 - Andrew E. Mileski
  183.  * Written, tested, and released.
  184.  */
  185. int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
  186. unsigned long arg)
  187. {
  188. int result = -EINVAL;
  189. struct buffer_head *bh = NULL;
  190. long_ad eaicb;
  191. Uint8 *ea = NULL;
  192. if ( permission(inode, MAY_READ) != 0 )
  193. {
  194. udf_debug("no permission to access inode %lun",
  195. inode->i_ino);
  196. return -EPERM;
  197. }
  198. if ( !arg )
  199. {
  200. udf_debug("invalid argument to udf_ioctln");
  201. return -EINVAL;
  202. }
  203. /* first, do ioctls that don't need to udf_read */
  204. switch (cmd)
  205. {
  206. case UDF_GETVOLIDENT:
  207. return copy_to_user((char *)arg,
  208. UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0;
  209. case UDF_RELOCATE_BLOCKS:
  210. {
  211. long old, new;
  212. if (!capable(CAP_SYS_ADMIN)) return -EACCES;
  213. if (get_user(old, (long *)arg)) return -EFAULT;
  214. if ((result = udf_relocate_blocks(inode->i_sb,
  215. old, &new)) == 0)
  216. result = put_user(new, (long *)arg);
  217. return result;
  218. }
  219. }
  220. /* ok, we need to read the inode */
  221. bh = udf_tread(inode->i_sb,
  222. udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
  223. if (!bh)
  224. {
  225. udf_debug("bread failed (inode=%ld)n", inode->i_ino);
  226. return -EIO;
  227. }
  228. if (UDF_I_EXTENDED_FE(inode) == 0)
  229. {
  230. struct FileEntry *fe;
  231. fe = (struct FileEntry *)bh->b_data;
  232. eaicb = lela_to_cpu(fe->extendedAttrICB);
  233. if (UDF_I_LENEATTR(inode))
  234. ea = fe->extendedAttr;
  235. }
  236. else
  237. {
  238. struct ExtendedFileEntry *efe;
  239. efe = (struct ExtendedFileEntry *)bh->b_data;
  240. eaicb = lela_to_cpu(efe->extendedAttrICB);
  241. if (UDF_I_LENEATTR(inode))
  242. ea = efe->extendedAttr;
  243. }
  244. switch (cmd) 
  245. {
  246. case UDF_GETEASIZE:
  247. result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
  248. break;
  249. case UDF_GETEABLOCK:
  250. result = copy_to_user((char *)arg, ea,
  251. UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
  252. break;
  253. }
  254. udf_release_data(bh);
  255. return result;
  256. }
  257. /*
  258.  * udf_release_file
  259.  *
  260.  * PURPOSE
  261.  *  Called when all references to the file are closed
  262.  *
  263.  * DESCRIPTION
  264.  *  Discard prealloced blocks
  265.  *
  266.  * HISTORY
  267.  *
  268.  */
  269. static int udf_release_file(struct inode * inode, struct file * filp)
  270. {
  271. if (filp->f_mode & FMODE_WRITE)
  272. {
  273. lock_kernel();
  274. udf_discard_prealloc(inode);
  275. unlock_kernel();
  276. }
  277. return 0;
  278. }
  279. /*
  280.  * udf_open_file
  281.  *
  282.  * PURPOSE
  283.  *  Called when an inode is about to be open.
  284.  *
  285.  * DESCRIPTION
  286.  *  Use this to disallow opening RW large files on 32 bit systems.
  287.  *  On 64 bit systems we force on O_LARGEFILE in sys_open.
  288.  *
  289.  * HISTORY
  290.  *
  291.  */
  292. static int udf_open_file(struct inode * inode, struct file * filp)
  293. {
  294. if ((inode->i_size & 0xFFFFFFFF80000000ULL) && !(filp->f_flags & O_LARGEFILE))
  295. return -EFBIG;
  296. return 0;
  297. }
  298. struct file_operations udf_file_operations = {
  299. read: generic_file_read,
  300. ioctl: udf_ioctl,
  301. open: udf_open_file,
  302. mmap: generic_file_mmap,
  303. write: udf_file_write,
  304. release: udf_release_file,
  305. fsync: udf_fsync_file,
  306. };
  307. struct inode_operations udf_file_inode_operations = {
  308. truncate: udf_truncate,
  309. };