2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <sys/types.h>
22 #include <netinet/in.h>
36 #define UBIK_INTERNALS 1
39 /* these routines are called via the proc ptr in the ubik_dbase structure. They provide access to
40 * the physical disk, by converting the file numbers being processed (>= 0 for user data space, < 0
41 * for ubik system files, such as the log) to actual pathnames to open, read, write, truncate, sync,
46 static struct fdcache {
50 } fdcache[MAXFDCACHE];
52 static char pbuffer[1024];
54 /* beware, when using this function, of the header in front of most files */
55 static int uphys_open(adbase, afid)
56 register struct ubik_dbase *adbase;
62 register struct fdcache *tfd;
63 struct fdcache *bestfd;
65 /* initialize package */
69 for(i=0;i<MAXFDCACHE;tfd++,i++) {
70 tfd->fd = -1; /* invalid value */
71 tfd->fileID = -10000; /* invalid value */
76 /* scan file descr cache */
77 for(tfd=fdcache,i=0; i<MAXFDCACHE; i++,tfd++) {
78 if (afid == tfd->fileID && tfd->refCount == 0) { /* don't use open fd */
79 lseek(tfd->fd, 0, 0); /* reset ptr just like open would have */
85 /* not found, open it and try to enter in cache */
86 strcpy(pbuffer, adbase->pathName);
87 strcat(pbuffer, ".DB");
90 strcat(pbuffer, "SYS");
93 sprintf(temp, "%d", i);
94 strcat(pbuffer, temp);
95 fd = open(pbuffer, O_CREAT | O_RDWR, 0600);
97 /* try opening read-only */
98 fd = open(pbuffer, O_RDONLY, 0);
99 if (fd < 0) return fd;
102 /* enter it in the cache */
105 for(i=0;i<MAXFDCACHE;i++,tfd++) { /* look for empty slot */
111 if (!bestfd) { /* look for reclaimable slot */
113 for(i=0;i<MAXFDCACHE;i++,tfd++) {
114 if (tfd->refCount == 0) {
120 if (bestfd) { /* found a usable slot */
122 if (tfd->fd >= 0) close(tfd->fd);
124 tfd->refCount = 1; /* us */
128 /* finally, we're done */
132 /* close the file, maintaining ref count in cache structure */
136 register struct fdcache *tfd;
138 if (afd < 0) return EBADF;
140 for(i=0;i<MAXFDCACHE;i++,tfd++) {
141 if (tfd->fd == afd) {
149 uphys_stat(adbase, afid, astat)
150 struct ubik_stat *astat;
152 struct ubik_dbase *adbase; {
155 register afs_int32 code;
157 fd = uphys_open(adbase, afid);
158 if (fd < 0) return fd;
159 code = fstat(fd, &tstat);
164 astat->mtime = tstat.st_mtime;
165 code = tstat.st_size-HDRSIZE;
166 if (code < 0) astat->size = 0;
167 else astat->size = code;
171 uphys_read(adbase, afile, abuffer, apos, alength)
172 register struct ubik_dbase *adbase;
173 register char *abuffer;
178 register afs_int32 code;
180 fd = uphys_open(adbase, afile);
181 if (fd < 0) return -1;
182 code = lseek(fd, apos+HDRSIZE, 0);
187 code = read(fd, abuffer, alength);
192 uphys_write(adbase, afile, abuffer, apos, alength)
193 register struct ubik_dbase *adbase;
194 register char *abuffer;
199 register afs_int32 code;
202 fd = uphys_open(adbase, afile);
203 if (fd < 0) return -1;
204 code = lseek(fd, apos+HDRSIZE, 0);
209 length = write(fd, abuffer, alength);
210 code = uphys_close(fd);
215 uphys_truncate(adbase, afile, asize)
217 register struct ubik_dbase *adbase;
219 register afs_int32 code, fd;
220 fd = uphys_open(adbase, afile);
221 if (fd < 0) return UNOENT;
222 code = ftruncate(fd, asize+HDRSIZE);
227 /* get number of dbase files */
228 uphys_getnfiles(adbase) {
229 /* really should scan dir for data */
233 /* get database label, with aversion in host order */
234 uphys_getlabel(adbase, afile, aversion)
235 register struct ubik_dbase *adbase;
237 struct ubik_version *aversion; {
238 struct ubik_hdr thdr;
239 register afs_int32 code, fd;
241 fd = uphys_open(adbase, afile);
242 if (fd < 0) return UNOENT;
243 code = read(fd, &thdr, sizeof(thdr));
244 if (code != sizeof(thdr)) {
248 aversion->epoch = ntohl(thdr.version.epoch);
249 aversion->counter=ntohl(thdr.version.counter);
254 /* label database, with aversion in host order */
255 uphys_setlabel(adbase, afile, aversion)
256 register struct ubik_dbase *adbase;
258 struct ubik_version *aversion; {
259 struct ubik_hdr thdr;
260 register afs_int32 code, fd;
262 fd = uphys_open(adbase, afile);
263 if (fd < 0) return UNOENT;
264 thdr.version.epoch = htonl(aversion->epoch);
265 thdr.version.counter = htonl(aversion->counter);
266 thdr.magic = htonl(UBIK_MAGIC);
267 thdr.size = htonl(HDRSIZE);
268 code = write(fd, &thdr, sizeof(thdr));
269 fsync(fd); /* preserve over crash */
271 if (code != sizeof(thdr)) {
277 uphys_sync(adbase, afile)
278 register struct ubik_dbase *adbase;
280 register afs_int32 code, fd;
281 fd = uphys_open(adbase, afile);