diff options
Diffstat (limited to 'src/fs/file_dev.c')
-rw-r--r-- | src/fs/file_dev.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/fs/file_dev.c b/src/fs/file_dev.c new file mode 100644 index 0000000..4661b6f --- /dev/null +++ b/src/fs/file_dev.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * linux/fs/file_dev.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | #include <errno.h> | ||
8 | #include <fcntl.h> | ||
9 | |||
10 | #include <linux/sched.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <asm/segment.h> | ||
13 | |||
14 | #define MIN(a,b) (((a)<(b))?(a):(b)) | ||
15 | #define MAX(a,b) (((a)>(b))?(a):(b)) | ||
16 | |||
17 | int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) | ||
18 | { | ||
19 | int left,chars,nr; | ||
20 | struct buffer_head * bh; | ||
21 | |||
22 | if ((left=count)<=0) | ||
23 | return 0; | ||
24 | while (left) { | ||
25 | if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) { | ||
26 | if (!(bh=bread(inode->i_dev,nr))) | ||
27 | break; | ||
28 | } else | ||
29 | bh = NULL; | ||
30 | nr = filp->f_pos % BLOCK_SIZE; | ||
31 | chars = MIN( BLOCK_SIZE-nr , left ); | ||
32 | filp->f_pos += chars; | ||
33 | left -= chars; | ||
34 | if (bh) { | ||
35 | char * p = nr + bh->b_data; | ||
36 | while (chars-->0) | ||
37 | put_fs_byte(*(p++),buf++); | ||
38 | brelse(bh); | ||
39 | } else { | ||
40 | while (chars-->0) | ||
41 | put_fs_byte(0,buf++); | ||
42 | } | ||
43 | } | ||
44 | inode->i_atime = CURRENT_TIME; | ||
45 | return (count-left)?(count-left):-ERROR; | ||
46 | } | ||
47 | |||
48 | int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) | ||
49 | { | ||
50 | off_t pos; | ||
51 | int block,c; | ||
52 | struct buffer_head * bh; | ||
53 | char * p; | ||
54 | int i=0; | ||
55 | |||
56 | /* | ||
57 | * ok, append may not work when many processes are writing at the same time | ||
58 | * but so what. That way leads to madness anyway. | ||
59 | */ | ||
60 | if (filp->f_flags & O_APPEND) | ||
61 | pos = inode->i_size; | ||
62 | else | ||
63 | pos = filp->f_pos; | ||
64 | while (i<count) { | ||
65 | if (!(block = create_block(inode,pos/BLOCK_SIZE))) | ||
66 | break; | ||
67 | if (!(bh=bread(inode->i_dev,block))) | ||
68 | break; | ||
69 | c = pos % BLOCK_SIZE; | ||
70 | p = c + bh->b_data; | ||
71 | bh->b_dirt = 1; | ||
72 | c = BLOCK_SIZE-c; | ||
73 | if (c > count-i) c = count-i; | ||
74 | pos += c; | ||
75 | if (pos > inode->i_size) { | ||
76 | inode->i_size = pos; | ||
77 | inode->i_dirt = 1; | ||
78 | } | ||
79 | i += c; | ||
80 | while (c-->0) | ||
81 | *(p++) = get_fs_byte(buf++); | ||
82 | brelse(bh); | ||
83 | } | ||
84 | inode->i_mtime = CURRENT_TIME; | ||
85 | if (!(filp->f_flags & O_APPEND)) { | ||
86 | filp->f_pos = pos; | ||
87 | inode->i_ctime = CURRENT_TIME; | ||
88 | } | ||
89 | return (i?i:-1); | ||
90 | } | ||