|
|
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.