convert-from-bsd-to-posix-string-and-memory-functions-20010807
[openafs.git] / src / budb / database.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15 #ifdef AFS_NT40_ENV
16 #include <winsock2.h>
17 #else
18 #include <netinet/in.h>
19 #endif
20 #include <sys/types.h>
21 #include <afs/stds.h>
22 #include <ubik.h>
23 #include <afs/auth.h>
24 #include <afs/bubasics.h>
25 #include "budb_errs.h"
26 #include "database.h"
27 #include "error_macros.h"
28 #include "afs/audit.h"
29
30
31
32 int    pollCount;
33 struct memoryDB db;                     /* really allocate it here */
34
35 void db_panic (reason)
36   char *reason;
37 {
38     LogError(0, "db_panic: %s\n", reason);
39     BUDB_EXIT(-1);
40 }
41
42 afs_int32 InitDB ()
43 {   afs_int32  code;
44
45     pollCount = 0;
46
47     memset(&db, 0, sizeof(db));
48     Lock_Init (&db.lock);
49     if ((code = InitDBalloc ()) || (code = InitDBhash ())) 
50         return code;
51     return 0;
52 }
53
54 /* package up seek and write into one procedure for ease of use */
55
56 /* dbwrite 
57  *      write a portion of the database
58  * entry:
59  *      pos - offset into the database (disk address). If this is in the
60  *              database header, then buff must be a ptr to a portion of
61  *              the in-core header
62  *      buff - the information to write
63  *      len - size of the write
64  */
65
66 afs_int32 dbwrite (ut, pos, buff, len)
67   struct ubik_trans *ut;
68   afs_int32  pos;
69   char *buff;
70   afs_int32  len;
71 {
72     afs_int32 code = 0;
73
74     if ( ( (pos < sizeof(db.h)) && (buff != (char *)&db.h + pos) ) ||
75          (pos >= ntohl(db.h.eofPtr)) )
76     {
77         Log("dbwrite: Illegal attempt to write at location 0 or past EOF\n");
78         ERROR(BUDB_IO);
79     }
80
81     code = ubik_Seek(ut, 0, pos);
82     if (code)
83     {
84         LogError(code, "dbwrite: ubik_Seek to %d failed\n", pos);
85         ERROR(code);
86     }
87     code = ubik_Write(ut,buff,len);
88     if (code)
89     {
90         LogError(code, "dbwrite: ubik_Write failed\n");
91         ERROR(code);
92     }
93
94   error_exit:
95     if (((++pollCount) % 4) == 0)     /* Poll every 4 reads/writes */
96     {
97         IOMGR_Poll();
98         pollCount = 0;
99     }
100     return code;
101 }
102
103 /* same thing for read */
104
105 afs_int32 dbread (ut, pos, buff, len)
106   struct ubik_trans *ut;
107   afs_int32  pos;
108   char *buff;
109   afs_int32  len;
110 {
111     afs_int32 code = 0;
112
113     if (pos >= ntohl(db.h.eofPtr))
114     {
115         LogError(0, "dbread: Attempt to read @%d (past EOF)\n", pos);
116         ERROR(BUDB_IO);
117     }
118
119     code = ubik_Seek(ut, 0, pos);
120     if (code)
121     {
122         LogError(code, "dbread: ubik_Seek to %d failed\n", pos);
123         ERROR(code);
124     }
125     code = ubik_Read(ut, buff, len);
126     if (code)
127     {
128         LogError(code, "dbread: ubik_Read pos %d, buff %d, len %d\n", pos, buff, len);
129         ERROR(code);
130     }
131
132   error_exit:
133     if (((++pollCount) % 4) == 0)     /* Poll every 4 reads/writes */
134     {
135         IOMGR_Poll();
136         pollCount = 0;
137     }
138     return code;
139 }
140
141 /* Same as dbread excepts it does checking */
142 afs_int32 cdbread (ut, type, pos, buff, len)
143   struct ubik_trans *ut;
144   int    type;
145   afs_int32  pos;
146   char   *buff;
147   afs_int32  len;
148 {
149     afs_int32 code = 0;
150
151     code = checkDiskAddress(pos, type, 0, 0);
152     if (code)
153     {
154         LogError(code, "cdbread: Bad Address for block %d (addr 0x%x)\n", 
155                  type, pos);
156         ERROR(code);
157     }
158
159     code = ubik_Seek(ut, 0, pos);
160     if (code)
161     {
162         LogError(code, "cdbread: ubik_Seek to 0x%x failed\n", pos);
163         ERROR(code);
164     }
165     code = ubik_Read(ut, buff, len);
166     if (code)
167     {
168         LogError(code, "cdbread: ubik_Read pos 0x%x, buff %d, len %d\n", pos, buff, len);
169         ERROR(code);
170     }
171
172   error_exit:
173     if (((++pollCount) % 4) == 0)     /* Poll every 4 reads/writes */
174     {
175         IOMGR_Poll();
176         pollCount = 0;
177     }
178     return code;
179 }
180
181 /* check that the database has been initialized.  Be careful to fail in a safe
182    manner, to avoid bogusly reinitializing the db.  */
183
184 afs_int32
185 CheckInit (ut, db_init)
186      struct ubik_trans *ut;
187      int (*db_init)();          /* procedure to call if rebuilding DB */
188 {   
189     register afs_int32 code;
190
191     /* Don't read header if not necessary */
192     if (!ubik_CacheUpdate (ut)) return 0;
193
194     ObtainWriteLock (&db.lock);
195
196     db.h.eofPtr = htonl(sizeof(db.h));  /* for sanity check in dbread */
197     code = dbread(ut, 0, (char *) &db.h, sizeof(db.h));
198     if (code) ERROR(code);
199
200     if ((ntohl(db.h.version) != BUDB_VERSION) || (ntohl(db.h.checkVersion) != BUDB_VERSION))
201     {
202
203         if ((ntohl(db.h.version) == 0) || (ntohl(db.h.checkVersion) == 0))
204             ERROR(BUDB_EMPTY);
205
206         LogError(0, "DB version should be %d; Initial = %d; Terminal = %d\n",
207                     BUDB_VERSION, ntohl(db.h.version), ntohl(db.h.checkVersion));
208         ERROR(BUDB_IO);
209     }
210
211     db.readTime = time(0);
212     ht_Reset (&db.volName);
213     ht_Reset (&db.tapeName);
214     ht_Reset (&db.dumpName);
215     ht_Reset (&db.dumpIden);
216
217   error_exit:
218     ReleaseWriteLock (&db.lock);
219     if (code)
220     {
221         if ((code == UEOF) || (code == BUDB_EMPTY))
222         {
223             if (db_init)
224             {
225                 LogDebug(0, "No data base - Building new one\n");
226
227                 /* try to write a good header */
228                 memset(&db.h, 0, sizeof(db.h));
229                 db.h.version = htonl(BUDB_VERSION);
230                 db.h.checkVersion = htonl(BUDB_VERSION);
231                 db.h.lastUpdate = db.h.lastDumpId = htonl(time(0));
232                 db.h.eofPtr = htonl(sizeof(db.h));
233
234                 /* text ptrs cleared by bzero */
235                 ht_DBInit ();
236
237                 code = dbwrite(ut, 0, (char *) &db.h, sizeof(db.h));
238                 if (code) code = BUDB_IO;       /* return the error code */
239                 else      code = db_init(ut);   /* initialize the db */
240             }
241             else
242             {
243                 LogDebug(0, "No data base\n");
244                 code = BUDB_EMPTY;
245             }
246         }
247         else
248         {
249             LogDebug(0, "I/O Error\n");
250             code = BUDB_IO;
251         }
252     }
253     return code;
254 }