Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 #define trace 1
7 u32int maxblocksize;
8 int readonly;
10 Part*
11 initpart(char *name, int writable)
12 {
13 Part *part;
14 Dir *dir;
15 int how;
17 part = MKZ(Part);
18 part->name = estrdup(name);
19 if(!writable && readonly)
20 how = OREAD;
21 else
22 how = ORDWR;
23 part->fd = open(name, how);
24 if(part->fd < 0){
25 if(how == ORDWR)
26 part->fd = open(name, OREAD);
27 if(part->fd < 0){
28 freepart(part);
29 seterr(EOk, "can't open partition='%s': %r", name);
30 return nil;
31 }
32 fprint(2, "warning: %s opened for reading only\n", name);
33 }
34 dir = dirfstat(part->fd);
35 if(dir == nil){
36 freepart(part);
37 seterr(EOk, "can't stat partition='%s': %r", name);
38 return nil;
39 }
40 part->size = dir->length;
41 part->blocksize = 0;
42 free(dir);
43 return part;
44 }
46 void
47 freepart(Part *part)
48 {
49 if(part == nil)
50 return;
51 close(part->fd);
52 free(part->name);
53 free(part);
54 }
56 void
57 partblocksize(Part *part, u32int blocksize)
58 {
59 if(part->blocksize)
60 sysfatal("resetting partition=%s's block size", part->name);
61 part->blocksize = blocksize;
62 if(blocksize > maxblocksize)
63 maxblocksize = blocksize;
64 }
66 int
67 writepart(Part *part, u64int addr, u8int *buf, u32int n)
68 {
69 long m, mm, nn;
71 qlock(&stats.lock);
72 stats.diskwrites++;
73 stats.diskbwrites += n;
74 qunlock(&stats.lock);
76 if(addr > part->size || addr + n > part->size){
77 seterr(ECorrupt, "out of bounds write to partition='%s'", part->name);
78 return -1;
79 }
80 if(trace) print("write %s %lud at %llud\n", part->name, n, addr);
81 for(nn = 0; nn < n; nn += m){
82 mm = n - nn;
83 if(mm > MaxIo)
84 mm = MaxIo;
85 m = pwrite(part->fd, &buf[nn], mm, addr + nn);
86 if(m != mm){
87 if(m < 0){
88 seterr(EOk, "can't write partition='%s': %r", part->name);
89 return -1;
90 }
91 logerr(EOk, "truncated write to partition='%s' n=%ld wrote=%ld", part->name, mm, m);
92 }
93 }
94 return 0;
95 }
97 int
98 readpart(Part *part, u64int addr, u8int *buf, u32int n)
99 {
100 long m, mm, nn;
101 int i;
103 qlock(&stats.lock);
104 stats.diskreads++;
105 stats.diskbreads += n;
106 qunlock(&stats.lock);
108 if(addr > part->size || addr + n > part->size){
109 seterr(ECorrupt, "out of bounds read from partition='%s': addr=%lld n=%d size=%lld", part->name, addr, n, part->size);
110 return -1;
112 if(trace) print("read %s %lud at %llud\n", part->name, n, addr);
113 for(nn = 0; nn < n; nn += m){
114 mm = n - nn;
115 if(mm > MaxIo)
116 mm = MaxIo;
117 m = -1;
118 for(i=0; i<4; i++) {
119 m = pread(part->fd, &buf[nn], mm, addr + nn);
120 if(m == mm)
121 break;
123 if(m != mm){
124 if(m < 0){
125 seterr(EOk, "can't read partition='%s': %r", part->name);
126 return -1;
128 logerr(EOk, "warning: truncated read from partition='%s' n=%ld read=%ld", part->name, mm, m);
131 return 0;