comparison source/file.c @ 0:ed10291ff195

first commit
author mir3636
date Sun, 06 Jan 2019 19:27:03 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:ed10291ff195
1 //
2 // File descriptors
3 //
4
5 #include "types.h"
6 #include "defs.h"
7 #include "param.h"
8 #include "fs.h"
9 #include "file.h"
10 #include "spinlock.h"
11
12 struct devsw devsw[NDEV];
13 struct {
14 struct spinlock lock;
15 struct file file[NFILE];
16 } ftable;
17
18 void
19 fileinit(void)
20 {
21 memset(&ftable, 0, sizeof(ftable));
22 initlock(&ftable.lock, "ftable");
23 }
24
25 // Allocate a file structure.
26 struct file*
27 filealloc(void)
28 {
29 struct file *f;
30
31 acquire(&ftable.lock);
32 for(f = ftable.file; f < ftable.file + NFILE; f++){
33 if(f->ref == 0){
34 f->ref = 1;
35 release(&ftable.lock);
36 return f;
37 }
38 }
39 release(&ftable.lock);
40 return 0;
41 }
42
43 // Increment ref count for file f.
44 struct file*
45 filedup(struct file *f)
46 {
47 acquire(&ftable.lock);
48 if(f->ref < 1)
49 panic("filedup");
50 f->ref++;
51 release(&ftable.lock);
52 return f;
53 }
54
55 // Close file f. (Decrement ref count, close when reaches 0.)
56 void
57 fileclose(struct file *f)
58 {
59 struct file ff;
60
61 acquire(&ftable.lock);
62 if(f->ref < 1)
63 panic("fileclose");
64 if(--f->ref > 0){
65 release(&ftable.lock);
66 return;
67 }
68 ff = *f;
69 f->ref = 0;
70 f->type = FD_NONE;
71 release(&ftable.lock);
72
73 if(ff.type == FD_PIPE)
74 pipeclose(ff.pipe, ff.writable);
75 else if(ff.type == FD_INODE){
76 begin_trans();
77 iput(ff.ip);
78 commit_trans();
79 }
80 }
81
82 // Get metadata about file f.
83 int
84 filestat(struct file *f, struct stat *st)
85 {
86 if(f->type == FD_INODE){
87 ilock(f->ip);
88 stati(f->ip, st);
89 iunlock(f->ip);
90 return 0;
91 }
92 return -1;
93 }
94
95 // Read from file f.
96 int
97 fileread(struct file *f, char *addr, int n)
98 {
99 int r;
100
101 if(f->readable == 0)
102 return -1;
103 if(f->type == FD_PIPE)
104 return piperead(f->pipe, addr, n);
105 if(f->type == FD_INODE){
106 ilock(f->ip);
107 //cprintf("inside fileread\n");
108 if((r = readi(f->ip, addr, f->off, n)) > 0)
109 f->off += r;
110 //cprintf("inside fileread: after readi rv=%x\n", r);
111 iunlock(f->ip);
112 return r;
113 }
114 panic("fileread");
115 return -1;
116 }
117
118 //PAGEBREAK!
119 // Write to file f.
120 int
121 filewrite(struct file *f, char *addr, int n)
122 {
123 int r;
124
125 if(f->writable == 0)
126 return -1;
127 //cprintf("inside filewrite\n");
128 if(f->type == FD_PIPE)
129 return pipewrite(f->pipe, addr, n);
130 if(f->type == FD_INODE){
131 // write a few blocks at a time to avoid exceeding
132 // the maximum log transaction size, including
133 // i-node, indirect block, allocation blocks,
134 // and 2 blocks of slop for non-aligned writes.
135 // this really belongs lower down, since writei()
136 // might be writing a device like the console.
137 int max = ((LOGSIZE-1-1-2) / 2) * 512;
138 int i = 0;
139 while(i < n){
140 int n1 = n - i;
141 if(n1 > max)
142 n1 = max;
143
144 begin_trans();
145 ilock(f->ip);
146 if ((r = writei(f->ip, addr + i, f->off, n1)) > 0)
147 f->off += r;
148 iunlock(f->ip);
149 commit_trans();
150
151 if(r < 0)
152 break;
153 if(r != n1)
154 panic("short filewrite");
155 i += r;
156 }
157 return i == n ? n : -1;
158 }
159 panic("filewrite");
160 return -1;
161 }
162