|
|
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:
1.1.1.2 ! root 85: /* printk("msdos_file_read\n"); */
1.1 root 86: if (!inode) {
1.1.1.2 ! root 87: printk("msdos_file_read: inode = NULL\n");
1.1 root 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));
1.1.1.2 ! root 102: if (MSDOS_I(inode)->i_binary) {
1.1 root 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;
1.1.1.2 ! root 152: if (error) {
! 153: msdos_truncate(inode);
! 154: break;
! 155: }
1.1 root 156: offset = filp->f_pos & (SECTOR_SIZE-1);
157: size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
158: if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
159: error = -EIO;
160: break;
161: }
1.1.1.2 ! root 162: if (MSDOS_I(inode)->i_binary) {
1.1 root 163: memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
164: buf,written = size);
165: buf += size;
166: }
167: else {
168: written = left = SECTOR_SIZE-offset;
169: to = data+(filp->f_pos & (SECTOR_SIZE-1));
170: if (carry) {
171: *to++ = '\n';
172: left--;
173: carry = 0;
174: }
175: for (size = 0; size < count && left; size++) {
176: if ((ch = get_fs_byte(buf++)) == '\n') {
177: *to++ = '\r';
178: left--;
179: }
180: if (!left) carry = 1;
181: else {
182: *to++ = ch;
183: left--;
184: }
185: }
186: written -= left;
187: }
188: filp->f_pos += written;
189: if (filp->f_pos > inode->i_size) {
190: inode->i_size = filp->f_pos;
191: inode->i_dirt = 1;
192: }
193: bh->b_dirt = 1;
194: brelse(bh);
195: }
196: inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1.1.1.2 ! root 197: MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
1.1 root 198: inode->i_dirt = 1;
199: return start == buf ? error : buf-start;
200: }
201:
202:
203: void msdos_truncate(struct inode *inode)
204: {
205: int cluster;
206:
207: cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
208: (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
1.1.1.2 ! root 209: MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
1.1 root 210: inode->i_dirt = 1;
211: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.