]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/venti/srv/part.c
venti: fix memory layers
[plan9front.git] / sys / src / cmd / venti / srv / part.c
1 #include "stdinc.h"
2 #include <ctype.h>
3 #include "dat.h"
4 #include "fns.h"
5
6 u32int  maxblocksize;
7 int     readonly;
8
9 static int
10 strtoullsuf(char *p, char **pp, int rad, u64int *u)
11 {
12         u64int v;
13
14         if(!isdigit((uchar)*p))
15                 return -1;
16         v = strtoull(p, &p, rad);
17         switch(*p){
18         case 'k':
19         case 'K':
20                 v *= 1024;
21                 p++;
22                 break;
23         case 'm':
24         case 'M':
25                 v *= 1024*1024;
26                 p++;
27                 break;
28         case 'g':
29         case 'G':
30                 v *= 1024*1024*1024;
31                 p++;
32                 break;
33         case 't':
34         case 'T':
35                 v *= 1024*1024;
36                 v *= 1024*1024;
37                 p++;
38                 break;
39         }
40         *pp = p;
41         *u = v;
42         return 0;
43 }
44         
45 static int
46 parsepart(char *name, char **file, u64int *lo, u64int *hi)
47 {
48         char *p;
49
50         *file = vtstrdup(name);
51         if((p = strrchr(*file, ':')) == nil){
52                 *lo = 0;
53                 *hi = 0;
54                 return 0;
55         }
56         *p++ = 0;
57         if(*p == '-')
58                 *lo = 0;
59         else{
60                 if(strtoullsuf(p, &p, 0, lo) < 0){
61                         free(*file);
62                         return -1;
63                 }
64         }
65         if(*p == '-')
66                 p++;
67         if(*p == 0){
68                 *hi = 0;
69                 return 0;
70         }
71         if(strtoullsuf(p, &p, 0, hi) < 0 || *p != 0){
72                 free(*file);
73                 return -1;
74         }
75         return 0;
76 }
77
78 Part*
79 initpart(char *name, int mode)
80 {
81         Part *part;
82         Dir *dir;
83         char *file;
84         u64int lo, hi;
85
86         if(parsepart(name, &file, &lo, &hi) < 0)
87                 return nil;
88         trace(TraceDisk, "initpart %s file %s lo 0x%llx hi 0x%llx", name, file, lo, hi);
89         part = MKZ(Part);
90         part->name = vtstrdup(name);
91         part->filename = vtstrdup(file);
92         if(readonly){
93                 mode &= ~(OREAD|OWRITE|ORDWR);
94                 mode |= OREAD;
95         }
96         part->fd = open(file, mode);
97         if(part->fd < 0){
98                 if((mode&(OREAD|OWRITE|ORDWR)) == ORDWR)
99                         part->fd = open(file, (mode&~ORDWR)|OREAD);
100                 if(part->fd < 0){
101                         freepart(part);
102                         fprint(2, "can't open partition='%s': %r\n", file);
103                         seterr(EOk, "can't open partition='%s': %r", file);
104                         fprint(2, "%r\n");
105                         free(file);
106                         return nil;
107                 }
108                 fprint(2, "warning: %s opened for reading only\n", name);
109         }
110         part->offset = lo;
111         dir = dirfstat(part->fd);
112         if(dir == nil){
113                 freepart(part);
114                 seterr(EOk, "can't stat partition='%s': %r", file);
115                 free(file);
116                 return nil;
117         }
118         if(dir->length == 0){
119                 free(dir);
120                 freepart(part);
121                 seterr(EOk, "can't determine size of partition %s", file);
122                 free(file);
123                 return nil;
124         }
125         if(dir->length < hi || dir->length < lo){
126                 freepart(part);
127                 seterr(EOk, "partition '%s': bounds out of range (max %lld)", name, dir->length);
128                 free(dir);
129                 free(file);
130                 return nil;
131         }
132         if(hi == 0)
133                 hi = dir->length;
134         part->size = hi - part->offset;
135         free(dir);
136         return part;
137 }
138
139 int
140 flushpart(Part *part)
141 {
142         USED(part);
143         return 0;
144 }
145
146 void
147 freepart(Part *part)
148 {
149         if(part == nil)
150                 return;
151         if(part->fd >= 0)
152                 close(part->fd);
153         free(part->name);
154         free(part);
155 }
156
157 void
158 partblocksize(Part *part, u32int blocksize)
159 {
160         if(part->blocksize)
161                 sysfatal("resetting partition=%s's block size", part->name);
162         part->blocksize = blocksize;
163         if(blocksize > maxblocksize)
164                 maxblocksize = blocksize;
165 }
166
167 enum {
168         Maxxfer = 64*1024,      /* for NCR SCSI controllers; was 128K */
169 };
170
171 static int reopen(Part*);
172
173 int
174 rwpart(Part *part, int isread, u64int offset0, u8int *buf0, u32int count0)
175 {
176         u32int count, opsize;
177         int n;
178         u8int *buf;
179         u64int offset;
180
181         trace(TraceDisk, "%s %s %ud at 0x%llx", 
182                 isread ? "read" : "write", part->name, count0, offset0);
183         if(offset0 >= part->size || offset0+count0 > part->size){
184                 seterr(EStrange, "out of bounds %s offset 0x%llux count %ud to partition %s size 0x%llux",
185                         isread ? "read" : "write", offset0, count0, part->name,
186                         part->size);
187                 return -1;
188         }
189
190         buf = buf0;
191         count = count0;
192         offset = offset0;
193         while(count > 0){
194                 opsize = count;
195                 if(opsize > Maxxfer)
196                         opsize = Maxxfer;
197                 if(isread)
198                         n = pread(part->fd, buf, opsize, offset);
199                 else
200                         n = pwrite(part->fd, buf, opsize, offset);
201                 if(n <= 0){
202                         seterr(EAdmin, "%s %s offset 0x%llux count %ud buf %p returned %d: %r",
203                                 isread ? "read" : "write", part->filename, offset, opsize, buf, n);
204                         return -1;
205                 }
206                 offset += n;
207                 count -= n;
208                 buf += n;
209         }
210
211         return count0;
212 }
213
214 int
215 readpart(Part *part, u64int offset, u8int *buf, u32int count)
216 {
217         return rwpart(part, 1, offset, buf, count);
218 }
219
220 int
221 writepart(Part *part, u64int offset, u8int *buf, u32int count)
222 {
223         return rwpart(part, 0, offset, buf, count);
224 }
225
226 ZBlock*
227 readfile(char *name)
228 {
229         Part *p;
230         ZBlock *b;
231
232         p = initpart(name, OREAD);
233         if(p == nil)
234                 return nil;
235         b = alloczblock(p->size, 0, p->blocksize);
236         if(b == nil){
237                 seterr(EOk, "can't alloc %s: %r", name);
238                 freepart(p);
239                 return nil;
240         }
241         if(readpart(p, 0, b->data, p->size) < 0){
242                 seterr(EOk, "can't read %s: %r", name);
243                 freepart(p);
244                 freezblock(b);
245                 return nil;
246         }
247         freepart(p);
248         return b;
249 }