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-2004 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 * ICBTAG_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 33 #include "udfdecl.h" 34 #include <linux/fs.h> 35 #include <linux/udf_fs.h> 36 #include <asm/uaccess.h> 37 #include <linux/kernel.h> 38 #include <linux/string.h> /* memset */ 39 #include <linux/errno.h> 40 #include <linux/smp_lock.h> 41 #include <linux/pagemap.h> 42 #include <linux/buffer_head.h> 43 44 #include "udf_i.h" 45 #include "udf_sb.h" 46 47 static int udf_adinicb_readpage(struct file *file, struct page * page) 48 { 49 struct inode *inode = page->mapping->host; 50 char *kaddr; 51 52 BUG_ON(!PageLocked(page)); 53 54 kaddr = kmap(page); 55 memset(kaddr, 0, PAGE_CACHE_SIZE); 56 memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size); 57 flush_dcache_page(page); 58 SetPageUptodate(page); 59 kunmap(page); 60 unlock_page(page); 61 return 0; 62 } 63 64 static int udf_adinicb_writepage(struct page *page, struct writeback_control *wbc) 65 { 66 struct inode *inode = page->mapping->host; 67 char *kaddr; 68 69 BUG_ON(!PageLocked(page)); 70 71 kaddr = kmap(page); 72 memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size); 73 mark_inode_dirty(inode); 74 SetPageUptodate(page); 75 kunmap(page); 76 unlock_page(page); 77 return 0; 78 } 79 80 static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) 81 { 82 kmap(page); 83 return 0; 84 } 85 86 static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) 87 { 88 struct inode *inode = page->mapping->host; 89 char *kaddr = page_address(page); 90 91 memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 92 kaddr + offset, to - offset); 93 mark_inode_dirty(inode); 94 SetPageUptodate(page); 95 kunmap(page); 96 /* only one page here */ 97 if (to > inode->i_size) 98 inode->i_size = to; 99 return 0; 100 } 101 102 struct address_space_operations udf_adinicb_aops = { 103 .readpage = udf_adinicb_readpage, 104 .writepage = udf_adinicb_writepage, 105 .sync_page = block_sync_page, 106 .prepare_write = udf_adinicb_prepare_write, 107 .commit_write = udf_adinicb_commit_write, 108 }; 109 110 static ssize_t udf_file_write(struct file * file, const char __user * buf, 111 size_t count, loff_t *ppos) 112 { 113 ssize_t retval; 114 struct inode *inode = file->f_dentry->d_inode; 115 int err, pos; 116 117 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) 118 { 119 if (file->f_flags & O_APPEND) 120 pos = inode->i_size; 121 else 122 pos = *ppos; 123 124 if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + 125 pos + count)) 126 { 127 udf_expand_file_adinicb(inode, pos + count, &err); 128 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) 129 { 130 udf_debug("udf_expand_adinicb: err=%d\n", err); 131 return err; 132 } 133 } 134 else 135 { 136 if (pos + count > inode->i_size) 137 UDF_I_LENALLOC(inode) = pos + count; 138 else 139 UDF_I_LENALLOC(inode) = inode->i_size; 140 } 141 } 142 143 retval = generic_file_write(file, buf, count, ppos); 144 145 if (retval > 0) 146 mark_inode_dirty(inode); 147 return retval; 148 } 149 150 /* 151 * udf_ioctl 152 * 153 * PURPOSE 154 * Issue an ioctl. 155 * 156 * DESCRIPTION 157 * Optional - sys_ioctl() will return -ENOTTY if this routine is not 158 * available, and the ioctl cannot be handled without filesystem help. 159 * 160 * sys_ioctl() handles these ioctls that apply only to regular files: 161 * FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD 162 * These ioctls are also handled by sys_ioctl(): 163 * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC 164 * All other ioctls are passed to the filesystem. 165 * 166 * Refer to sys_ioctl() in fs/ioctl.c 167 * sys_ioctl() -> . 168 * 169 * PRE-CONDITIONS 170 * inode Pointer to inode that ioctl was issued on. 171 * filp Pointer to file that ioctl was issued on. 172 * cmd The ioctl command. 173 * arg The ioctl argument [can be interpreted as a 174 * user-space pointer if desired]. 175 * 176 * POST-CONDITIONS 177 * <return> Success (>=0) or an error code (<=0) that 178 * sys_ioctl() will return. 179 * 180 * HISTORY 181 * July 1, 1997 - Andrew E. Mileski 182 * Written, tested, and released. 183 */ 184 int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 185 unsigned long arg) 186 { 187 int result = -EINVAL; 188 189 if ( permission(inode, MAY_READ, NULL) != 0 ) 190 { 191 udf_debug("no permission to access inode %lu\n", 192 inode->i_ino); 193 return -EPERM; 194 } 195 196 if ( !arg ) 197 { 198 udf_debug("invalid argument to udf_ioctl\n"); 199 return -EINVAL; 200 } 201 202 switch (cmd) 203 { 204 case UDF_GETVOLIDENT: 205 return copy_to_user((char __user *)arg, 206 UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0; 207 case UDF_RELOCATE_BLOCKS: 208 { 209 long old, new; 210 211 if (!capable(CAP_SYS_ADMIN)) return -EACCES; 212 if (get_user(old, (long __user *)arg)) return -EFAULT; 213 if ((result = udf_relocate_blocks(inode->i_sb, 214 old, &new)) == 0) 215 result = put_user(new, (long __user *)arg); 216 217 return result; 218 } 219 case UDF_GETEASIZE: 220 result = put_user(UDF_I_LENEATTR(inode), (int __user *)arg); 221 break; 222 223 case UDF_GETEABLOCK: 224 result = copy_to_user((char __user *)arg, UDF_I_DATA(inode), 225 UDF_I_LENEATTR(inode)) ? -EFAULT : 0; 226 break; 227 } 228 229 return result; 230 } 231 232 /* 233 * udf_release_file 234 * 235 * PURPOSE 236 * Called when all references to the file are closed 237 * 238 * DESCRIPTION 239 * Discard prealloced blocks 240 * 241 * HISTORY 242 * 243 */ 244 static int udf_release_file(struct inode * inode, struct file * filp) 245 { 246 if (filp->f_mode & FMODE_WRITE) 247 { 248 lock_kernel(); 249 udf_discard_prealloc(inode); 250 unlock_kernel(); 251 } 252 return 0; 253 } 254 255 struct file_operations udf_file_operations = { 256 .read = generic_file_read, 257 .ioctl = udf_ioctl, 258 .open = generic_file_open, 259 .mmap = generic_file_mmap, 260 .write = udf_file_write, 261 .release = udf_release_file, 262 .fsync = udf_fsync_file, 263 .sendfile = generic_file_sendfile, 264 }; 265 266 struct inode_operations udf_file_inode_operations = { 267 .truncate = udf_truncate, 268 }; 269