Blob


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