|
|
1.1 ! root 1: /* ! 2: * linux/fs/msdos/file.c ! 3: * ! 4: * Written 1992 by Werner Almesberger ! 5: * ! 6: * MS-DOS regular file handling primitives ! 7: */ ! 8: ! 9: #include <asm/segment.h> ! 10: #include <asm/system.h> ! 11: ! 12: #include <linux/sched.h> ! 13: #include <linux/fs.h> ! 14: #include <linux/msdos_fs.h> ! 15: #include <linux/errno.h> ! 16: #include <linux/fcntl.h> ! 17: #include <linux/stat.h> ! 18: ! 19: #define MIN(a,b) (((a) < (b)) ? (a) : (b)) ! 20: #define MAX(a,b) (((a) > (b)) ? (a) : (b)) ! 21: ! 22: static int msdos_file_read(struct inode *inode,struct file *filp,char *buf, ! 23: int count); ! 24: static int msdos_file_write(struct inode *inode,struct file *filp,char *buf, ! 25: int count); ! 26: ! 27: ! 28: static struct file_operations msdos_file_operations = { ! 29: NULL, /* lseek - default */ ! 30: msdos_file_read, /* read */ ! 31: msdos_file_write, /* write */ ! 32: NULL, /* readdir - bad */ ! 33: NULL, /* select - default */ ! 34: NULL, /* ioctl - default */ ! 35: NULL, /* no special open is needed */ ! 36: NULL /* release */ ! 37: }; ! 38: ! 39: struct inode_operations msdos_file_inode_operations = { ! 40: &msdos_file_operations, /* default file operations */ ! 41: NULL, /* create */ ! 42: NULL, /* lookup */ ! 43: NULL, /* link */ ! 44: NULL, /* unlink */ ! 45: NULL, /* symlink */ ! 46: NULL, /* mkdir */ ! 47: NULL, /* rmdir */ ! 48: NULL, /* mknod */ ! 49: NULL, /* rename */ ! 50: NULL, /* readlink */ ! 51: NULL, /* follow_link */ ! 52: msdos_bmap, /* bmap */ ! 53: msdos_truncate /* truncate */ ! 54: }; ! 55: ! 56: /* No bmap for MS-DOS FS' that don't align data at kByte boundaries. */ ! 57: ! 58: struct inode_operations msdos_file_inode_operations_no_bmap = { ! 59: &msdos_file_operations, /* default file operations */ ! 60: NULL, /* create */ ! 61: NULL, /* lookup */ ! 62: NULL, /* link */ ! 63: NULL, /* unlink */ ! 64: NULL, /* symlink */ ! 65: NULL, /* mkdir */ ! 66: NULL, /* rmdir */ ! 67: NULL, /* mknod */ ! 68: NULL, /* rename */ ! 69: NULL, /* readlink */ ! 70: NULL, /* follow_link */ ! 71: NULL, /* bmap */ ! 72: msdos_truncate /* truncate */ ! 73: }; ! 74: ! 75: ! 76: static int msdos_file_read(struct inode *inode,struct file *filp,char *buf, ! 77: int count) ! 78: { ! 79: char *start; ! 80: int left,offset,size,sector,cnt; ! 81: char ch; ! 82: struct buffer_head *bh; ! 83: void *data; ! 84: ! 85: /* printk("msdos_file_read\r\n"); */ ! 86: if (!inode) { ! 87: printk("msdos_file_read: inode = NULL\r\n"); ! 88: return -EINVAL; ! 89: } ! 90: if (!S_ISREG(inode->i_mode)) { ! 91: printk("msdos_file_read: mode = %07o\n",inode->i_mode); ! 92: return -EINVAL; ! 93: } ! 94: if (filp->f_pos >= inode->i_size || count <= 0) return 0; ! 95: start = buf; ! 96: while (left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) { ! 97: if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS))) ! 98: break; ! 99: offset = filp->f_pos & (SECTOR_SIZE-1); ! 100: if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break; ! 101: filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left)); ! 102: if (inode->i_data[D_BINARY]) { ! 103: memcpy_tofs(buf,data+offset,size); ! 104: buf += size; ! 105: } ! 106: else for (cnt = size; cnt; cnt--) { ! 107: if ((ch = *((char *) data+offset++)) == '\r') ! 108: size--; ! 109: else { ! 110: if (ch != 26) put_fs_byte(ch,buf++); ! 111: else { ! 112: filp->f_pos = inode->i_size; ! 113: brelse(bh); ! 114: return buf-start; ! 115: } ! 116: } ! 117: } ! 118: brelse(bh); ! 119: } ! 120: if (start == buf) return -EIO; ! 121: return buf-start; ! 122: } ! 123: ! 124: ! 125: static int msdos_file_write(struct inode *inode,struct file *filp,char *buf, ! 126: int count) ! 127: { ! 128: int sector,offset,size,left,written; ! 129: int error,carry; ! 130: char *start,*to,ch; ! 131: struct buffer_head *bh; ! 132: void *data; ! 133: ! 134: if (!inode) { ! 135: printk("msdos_file_write: inode = NULL\n"); ! 136: return -EINVAL; ! 137: } ! 138: if (!S_ISREG(inode->i_mode)) { ! 139: printk("msdos_file_write: mode = %07o\n",inode->i_mode); ! 140: return -EINVAL; ! 141: } ! 142: /* ! 143: * ok, append may not work when many processes are writing at the same time ! 144: * but so what. That way leads to madness anyway. ! 145: */ ! 146: if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size; ! 147: if (count <= 0) return 0; ! 148: error = carry = 0; ! 149: for (start = buf; count || carry; count -= size) { ! 150: while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS))) ! 151: if ((error = msdos_add_cluster(inode)) < 0) break; ! 152: if (error) break; ! 153: offset = filp->f_pos & (SECTOR_SIZE-1); ! 154: size = MIN(SECTOR_SIZE-offset,MAX(carry,count)); ! 155: if (!(bh = msdos_sread(inode->i_dev,sector,&data))) { ! 156: error = -EIO; ! 157: break; ! 158: } ! 159: if (inode->i_data[D_BINARY]) { ! 160: memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)), ! 161: buf,written = size); ! 162: buf += size; ! 163: } ! 164: else { ! 165: written = left = SECTOR_SIZE-offset; ! 166: to = data+(filp->f_pos & (SECTOR_SIZE-1)); ! 167: if (carry) { ! 168: *to++ = '\n'; ! 169: left--; ! 170: carry = 0; ! 171: } ! 172: for (size = 0; size < count && left; size++) { ! 173: if ((ch = get_fs_byte(buf++)) == '\n') { ! 174: *to++ = '\r'; ! 175: left--; ! 176: } ! 177: if (!left) carry = 1; ! 178: else { ! 179: *to++ = ch; ! 180: left--; ! 181: } ! 182: } ! 183: written -= left; ! 184: } ! 185: filp->f_pos += written; ! 186: if (filp->f_pos > inode->i_size) { ! 187: inode->i_size = filp->f_pos; ! 188: inode->i_dirt = 1; ! 189: } ! 190: bh->b_dirt = 1; ! 191: brelse(bh); ! 192: } ! 193: inode->i_mtime = inode->i_ctime = CURRENT_TIME; ! 194: inode->i_data[D_ATTRS] |= ATTR_ARCH; ! 195: inode->i_dirt = 1; ! 196: return start == buf ? error : buf-start; ! 197: } ! 198: ! 199: ! 200: void msdos_truncate(struct inode *inode) ! 201: { ! 202: int cluster; ! 203: ! 204: cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size; ! 205: (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster); ! 206: inode->i_data[D_ATTRS] |= ATTR_ARCH; ! 207: inode->i_dirt = 1; ! 208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.