clean up headers, obsd socket.h needs types.h
[arla.git] / arlad / dynroot.c
blob4a7e43bc22d9d81fa32cd63130583fe56071dbbb
1 /*
2 * Copyright (c) 1999 - 2003, 2005-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
35 * Keep our own root.afs
37 * uses cell DYNROOTCELL as cell number.
40 #include <arla_local.h>
42 RCSID("$Id$");
44 struct create_entry {
45 fbuf *thedir; /* pointer to the fbuf that contains the dir */
46 AFSFid fid; /* the current fid */
47 int len; /* num of links in the dir */
48 int type;
51 #define DYNROOT_ROOTVOLUME 1 /* make sure that these */
52 #define DYNROOT_ROOTVOLUME_STR "1" /* two are the same */
53 #define DYNROOT_ROOTDIR 1
54 #define DYNROOT_UNIQUE 1
56 static Bool dynroot_enabled = 0; /* is dynroot enabled ? */
57 static unsigned long last_celldb_version = 0; /* last version of celldb */
60 * Magic glue wrt afsvnode#
63 static int32_t
64 cellnum2afs (int cellno, int rw)
66 if (rw)
67 return (cellno << 2) + 0x2;
68 else
69 return (cellno << 2) + 0x1;
72 static int
73 afs2cellnum (int32_t afsvnode, int *rw)
75 if (afsvnode & 0x2)
76 *rw = 1;
77 else
78 *rw = 0;
79 return afsvnode >> 2;
83 * helper functions for dynroot_create_root that for
84 * each `cell' with 'cellid' a entry in the root directory.
87 static int
88 create_entry_func (const char *name, uint32_t cellid, int type, void *arg)
90 struct create_entry *entry = (struct create_entry *) arg;
91 int ret;
93 entry->fid.Vnode = cellnum2afs (cellid, type & DYNROOT_ALIAS_READWRITE);
95 ret = fdir_creat (entry->thedir, name, NULL, entry->fid);
96 if (ret == 0) {
97 entry->len++;
98 } else if (ret == EEXIST) {
99 arla_warnx (ADEBWARN, "duplicate entry in dynroot: %s", name);
100 ret = 0;
103 return ret;
107 * Wrapper function for cell_foreach that takes a `cell' instead of a
108 * string and a cellid.
111 static int
112 create_cell_entry_func (const cell_entry *cell, void *arg)
114 char *rwname = NULL;
115 int ret;
117 if (!cell_dynroot(cell))
118 return 0;
120 ret = create_entry_func(cell->name, cell->id, DYNROOT_ALIAS_READONLY, arg);
121 if (ret)
122 return ret;
124 asprintf(&rwname, ".%s", cell->name);
125 if (rwname == NULL)
126 return 0;
128 ret = create_entry_func(rwname, cell->id, DYNROOT_ALIAS_READWRITE, arg);
129 free(rwname);
130 return ret;
137 static int
138 create_alias_entry_func (const char *cellname, const char *alias,
139 int type, void *arg)
141 cell_entry *cell;
143 cell = cell_get_by_name (cellname);
144 if (cell == NULL)
145 return 0;
146 return create_entry_func(alias, cell->id, type, arg);
152 * create the dynroot root directory in `fbuf', return number
153 * of entries in `len'.
156 static int
157 dynroot_create_root (fbuf *fbuf, size_t *len)
159 int ret;
160 AFSFid dot = { DYNROOT_ROOTVOLUME,
161 DYNROOT_ROOTDIR,
162 DYNROOT_UNIQUE};
163 struct create_entry entry;
165 ret = fdir_mkdir (fbuf, dot, dot, 0);
166 if (ret)
167 return ret;
169 entry.thedir = fbuf;
171 entry.fid.Volume = DYNROOT_ROOTVOLUME;
172 entry.fid.Vnode = DYNROOT_ROOTDIR + 2;
173 entry.fid.Unique = DYNROOT_UNIQUE;
174 entry.len = 0;
176 ret = cell_foreach (create_cell_entry_func, &entry);
177 if (ret)
178 return ret;
180 ret = cell_alias_foreach(create_alias_entry_func, &entry);
181 if (ret)
182 return ret;
184 *len = entry.len;
186 return 0;
190 * for the `vnode' create apropriate symlink in `fbuf'
193 static int
194 dynroot_create_symlink (fbuf *fbuf, int32_t vnode)
196 char *name;
197 cell_entry *cell;
198 int len, ret, rw = 0;
200 cell = cell_get_by_id (afs2cellnum (vnode, &rw));
201 if (cell == NULL)
202 return ENOENT;
204 len = asprintf (&name, "%c%s:root.cell.", rw ? '%' : '#', cell->name);
205 if (len == -1)
206 return ENOMEM;
208 ret = fbuf_truncate (fbuf, len);
209 if (ret == 0)
210 memmove (fbuf_buf(fbuf), name, len);
212 free(name);
213 return ret;
217 * Return TRUE if the combination `cell' and `volume' is
218 * in the dynroot.
221 Bool
222 dynroot_isvolumep (int cell, const char *volume)
224 assert (volume);
226 if (cell == 0 &&
227 (strcmp (volume, "root.afs") == 0
228 || strcmp (volume, DYNROOT_ROOTVOLUME_STR) == 0))
229 return TRUE;
231 return FALSE;
235 * Create a dummy nvldbentry in `entry'
239 dynroot_fetch_root_vldbN (nvldbentry *entry)
241 memset (entry, 0, sizeof(*entry));
243 strlcpy(entry->name, "root.afs", sizeof(entry->name));
244 entry->nServers = 0;
245 entry->volumeId[ROVOL] = DYNROOT_ROOTVOLUME;
246 entry->flags = VLF_ROEXISTS;
248 return 0;
252 * make sure `cred' is present in `entry'
254 static void
255 dynroot_set_access(FCacheEntry *entry, nnpfs_pag_t cred)
257 AccessEntry *ae;
258 if (findaccess(cred, entry->acccache, &ae) == FALSE) {
259 ae->cred = cred;
260 ae->access = entry->status.CallerAccess;
265 * Update `entry' to contain the correct information
266 * Note: doesn't update status.Length and status.LinkCount
269 static void
270 dynroot_update_entry (FCacheEntry *entry, int32_t filetype,
271 nnpfs_pag_t cred)
273 struct timeval tv;
275 assert (entry);
276 entry->status.InterfaceVersion = 1;
277 entry->status.FileType = filetype;
278 entry->status.DataVersion = 1;
279 entry->status.Author = 0;
280 entry->status.Owner = 0;
281 entry->status.CallerAccess = ALIST | AREAD;
282 entry->status.AnonymousAccess = ALIST | AREAD;
283 switch (filetype) {
284 case TYPE_DIR:
285 entry->status.UnixModeBits = 0755;
286 break;
287 case TYPE_LINK:
288 entry->status.UnixModeBits = 0644;
289 break;
290 default:
291 abort();
293 entry->status.ParentVnode = DYNROOT_ROOTDIR;
294 entry->status.ParentUnique = DYNROOT_UNIQUE;
295 entry->status.ResidencyMask = 1;
296 entry->status.ClientModTime = 0;
297 entry->status.ServerModTime = 0;
298 entry->status.Group = 0;
299 entry->status.SyncCounter = 0;
300 entry->status.DataVersionHigh= 0;
301 entry->status.LockCount = 0;
302 entry->status.LengthHigh = 0;
303 entry->status.ErrorCode = 0;
305 gettimeofday (&tv, NULL);
307 memset (&entry->volsync, 0, sizeof (entry->volsync));
309 entry->callback.CallBackVersion = 1;
310 entry->callback.ExpirationTime = tv.tv_sec + 3600 * 24 * 7;
311 entry->callback.CallBackType = CBSHARED;
313 entry->anonaccess = entry->status.AnonymousAccess;
314 dynroot_set_access(entry, cred);
318 * Fetch data and attr for `entry'
321 static int
322 dynroot_get_node (FCacheEntry *entry, CredCacheEntry *ce)
324 int ret, rootnode;
325 size_t len;
326 fbuf dir;
328 rootnode = entry->fid.fid.Vnode == DYNROOT_ROOTDIR ? 1 : 0;
330 if (entry->usage != 0 &&
331 (!rootnode || last_celldb_version == cell_get_version())) {
332 dynroot_set_access(entry, ce->cred); /* kernel may want access info */
333 return 0;
336 ret = abuf_create(&dir, entry, 0, FBUF_READ | FBUF_WRITE);
337 if (ret)
338 return ret;
340 if (rootnode) {
341 size_t nentries = 0;
342 ret = dynroot_create_root(&dir, &nentries);
343 entry->status.LinkCount = nentries;
344 } else {
345 ret = dynroot_create_symlink (&dir, entry->fid.fid.Vnode);
346 entry->status.LinkCount = 1;
349 if (ret) {
350 abuf_end(&dir);
351 return ret;
354 entry->flags.attrp = TRUE;
356 dynroot_update_entry (entry, rootnode ? TYPE_DIR : TYPE_LINK,
357 ce->cred);
359 if (!rootnode)
360 fcache_mark_as_mountpoint (entry);
362 len = fbuf_len(&dir);
363 fcache_set_have_all(entry, len);
365 ret = abuf_end(&dir);
366 if (ret)
367 return ret;
369 entry->tokens |= NNPFS_ATTR_R|NNPFS_DATA_R;
371 last_celldb_version = cell_get_version();
373 return 0;
377 * Fetch attr for `entry'
381 dynroot_get_attr (FCacheEntry *entry, CredCacheEntry *ce)
383 return dynroot_get_node (entry, ce);
388 * Fetch data for `entry'
392 dynroot_get_data (FCacheEntry *entry, CredCacheEntry *ce)
394 return dynroot_get_node (entry, ce);
398 * returns TRUE if `entry' is a dynroot entry.
401 Bool
402 dynroot_is_dynrootp (FCacheEntry *entry)
404 assert (entry);
406 if (dynroot_enabled &&
407 entry->fid.Cell == DYNROOT_CELLID &&
408 entry->fid.fid.Volume == DYNROOT_ROOTVOLUME)
409 return TRUE;
411 return FALSE;
415 * Return what status the dynroot is in.
418 Bool
419 dynroot_enablep (void)
421 return dynroot_enabled;
425 * Enable/Disable the dynroot depending on `enable', returns previous state.
428 Bool
429 dynroot_setenable (Bool enable)
431 Bool was = dynroot_enabled;
432 dynroot_enabled = enable;
433 return was;
437 * Returns the dynroot_cellid.
440 int32_t dynroot_cellid (void)
442 return DYNROOT_CELLID;
446 * Return the dynroot volumeid.
449 int32_t dynroot_volumeid (void)
451 return DYNROOT_ROOTVOLUME;