|
|
1.1 root 1: /*
2: * linux/fs/minix/file.c
3: *
4: * minix regular file handling primitives
5: */
6:
7: #include <errno.h>
8: #include <fcntl.h>
9:
10: #include <sys/dirent.h>
11: #include <sys/stat.h>
12:
13: #include <asm/segment.h>
14: #include <asm/system.h>
15:
16: #include <linux/sched.h>
17: #include <linux/minix_fs.h>
18: #include <linux/kernel.h>
19:
20: #define NBUF 16
21:
22: #define MIN(a,b) (((a)<(b))?(a):(b))
23: #define MAX(a,b) (((a)>(b))?(a):(b))
24:
25: #include <linux/fs.h>
26: #include <linux/minix_fs.h>
27:
28: int minix_file_read(struct inode *, struct file *, char *, int);
29: static int minix_file_write(struct inode *, struct file *, char *, int);
30:
31: /*
32: * We have mostly NULL's here: the current defaults are ok for
33: * the minix filesystem.
34: */
35: static struct file_operations minix_file_operations = {
36: NULL, /* lseek - default */
37: minix_file_read, /* read */
38: minix_file_write, /* write */
39: NULL, /* readdir - bad */
40: NULL, /* select - default */
41: NULL, /* ioctl - default */
42: NULL, /* no special open is needed */
43: NULL /* release */
44: };
45:
46: struct inode_operations minix_file_inode_operations = {
47: &minix_file_operations, /* default file operations */
48: NULL, /* create */
49: NULL, /* lookup */
50: NULL, /* link */
51: NULL, /* unlink */
52: NULL, /* symlink */
53: NULL, /* mkdir */
54: NULL, /* rmdir */
55: NULL, /* mknod */
56: NULL, /* rename */
57: NULL, /* readlink */
58: NULL, /* follow_link */
59: minix_bmap, /* bmap */
60: minix_truncate /* truncate */
61: };
62:
63: static inline void wait_on_buffer(struct buffer_head * bh)
64: {
65: cli();
66: while (bh->b_lock)
67: sleep_on(&bh->b_wait);
68: sti();
69: }
70:
71: /*
72: * minix_file_read() is also needed by the directory read-routine,
73: * so it's not static. NOTE! reading directories directly is a bad idea,
74: * but has to be supported for now for compatability reasons with older
75: * versions.
76: */
77: int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
78: {
79: int read,left,chars,nr;
80: int block, blocks, offset;
81: struct buffer_head ** bhb, ** bhe;
82: struct buffer_head * buflist[NBUF];
83:
84: if (!inode) {
85: printk("minix_file_read: inode = NULL\n");
86: return -EINVAL;
87: }
88: if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
89: printk("minix_file_read: mode = %07o\n",inode->i_mode);
90: return -EINVAL;
91: }
92: if (filp->f_pos > inode->i_size)
93: left = 0;
94: else
95: left = inode->i_size - filp->f_pos;
96: if (left > count)
97: left = count;
98: if (left <= 0)
99: return 0;
100: read = 0;
101: block = filp->f_pos >> BLOCK_SIZE_BITS;
102: offset = filp->f_pos & (BLOCK_SIZE-1);
103: blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
104: bhb = bhe = buflist;
105: do {
106: if (blocks) {
107: --blocks;
108: if (nr = minix_bmap(inode,block++)) {
109: *bhb = getblk(inode->i_dev,nr);
110: if (!(*bhb)->b_uptodate)
111: ll_rw_block(READ,*bhb);
112: } else
113: *bhb = NULL;
114:
115: if (++bhb == &buflist[NBUF])
116: bhb = buflist;
117:
118: if (bhb != bhe)
119: continue;
120: }
121: if (*bhe) {
122: wait_on_buffer(*bhe);
123: if (!(*bhe)->b_uptodate) {
124: do {
125: brelse(*bhe);
126: if (++bhe == &buflist[NBUF])
127: bhe = buflist;
128: } while (bhe != bhb);
129: break;
130: }
131: }
132:
133: if (left < BLOCK_SIZE - offset)
134: chars = left;
135: else
136: chars = BLOCK_SIZE - offset;
137: filp->f_pos += chars;
138: left -= chars;
139: read += chars;
140: if (*bhe) {
141: memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
142: brelse(*bhe);
143: buf += chars;
144: } else {
145: while (chars-->0)
146: put_fs_byte(0,buf++);
147: }
148: offset = 0;
149: if (++bhe == &buflist[NBUF])
150: bhe = buflist;
151: } while (left > 0);
152: if (!read)
153: return -EIO;
154: inode->i_atime = CURRENT_TIME;
155: inode->i_dirt = 1;
156: return read;
157: }
158:
159: static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
160: {
161: off_t pos;
162: int written,block,c;
163: struct buffer_head * bh;
164: char * p;
165:
166: if (!inode) {
167: printk("minix_file_write: inode = NULL\n");
168: return -EINVAL;
169: }
170: if (!S_ISREG(inode->i_mode)) {
171: printk("minix_file_write: mode = %07o\n",inode->i_mode);
172: return -EINVAL;
173: }
174: /*
175: * ok, append may not work when many processes are writing at the same time
176: * but so what. That way leads to madness anyway.
177: */
178: if (filp->f_flags & O_APPEND)
179: pos = inode->i_size;
180: else
181: pos = filp->f_pos;
182: written = 0;
183: while (written<count) {
184: if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
185: if (!written)
186: written = -ENOSPC;
187: break;
188: }
189: c = BLOCK_SIZE - (pos % BLOCK_SIZE);
190: if (c > count-written)
191: c = count-written;
192: if (c == BLOCK_SIZE)
193: bh = getblk(inode->i_dev, block);
194: else
195: bh = bread(inode->i_dev,block);
196: if (!bh) {
197: if (!written)
198: written = -EIO;
199: break;
200: }
201: p = (pos % BLOCK_SIZE) + bh->b_data;
202: pos += c;
203: if (pos > inode->i_size) {
204: inode->i_size = pos;
205: inode->i_dirt = 1;
206: }
207: written += c;
208: memcpy_fromfs(p,buf,c);
209: buf += c;
210: bh->b_uptodate = 1;
211: bh->b_dirt = 1;
212: brelse(bh);
213: }
214: inode->i_mtime = CURRENT_TIME;
215: if (!(filp->f_flags & O_APPEND)) {
216: filp->f_pos = pos;
217: inode->i_ctime = CURRENT_TIME;
218: }
219: inode->i_dirt = 1;
220: return written;
221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.