2 * Copyright (c) 1999 - 2003, 2005-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
35 * Keep our own root.afs
37 * uses cell DYNROOTCELL as cell number.
40 #include <arla_local.h>
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 */
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#
64 cellnum2afs (int cellno
, int rw
)
67 return (cellno
<< 2) + 0x2;
69 return (cellno
<< 2) + 0x1;
73 afs2cellnum (int32_t afsvnode
, int *rw
)
83 * helper functions for dynroot_create_root that for
84 * each `cell' with 'cellid' a entry in the root directory.
88 create_entry_func (const char *name
, uint32_t cellid
, int type
, void *arg
)
90 struct create_entry
*entry
= (struct create_entry
*) arg
;
93 entry
->fid
.Vnode
= cellnum2afs (cellid
, type
& DYNROOT_ALIAS_READWRITE
);
95 ret
= fdir_creat (entry
->thedir
, name
, NULL
, entry
->fid
);
98 } else if (ret
== EEXIST
) {
99 arla_warnx (ADEBWARN
, "duplicate entry in dynroot: %s", name
);
107 * Wrapper function for cell_foreach that takes a `cell' instead of a
108 * string and a cellid.
112 create_cell_entry_func (const cell_entry
*cell
, void *arg
)
117 if (!cell_dynroot(cell
))
120 ret
= create_entry_func(cell
->name
, cell
->id
, DYNROOT_ALIAS_READONLY
, arg
);
124 asprintf(&rwname
, ".%s", cell
->name
);
128 ret
= create_entry_func(rwname
, cell
->id
, DYNROOT_ALIAS_READWRITE
, arg
);
138 create_alias_entry_func (const char *cellname
, const char *alias
,
143 cell
= cell_get_by_name (cellname
);
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'.
157 dynroot_create_root (fbuf
*fbuf
, size_t *len
)
160 AFSFid dot
= { DYNROOT_ROOTVOLUME
,
163 struct create_entry entry
;
165 ret
= fdir_mkdir (fbuf
, dot
, dot
, 0);
171 entry
.fid
.Volume
= DYNROOT_ROOTVOLUME
;
172 entry
.fid
.Vnode
= DYNROOT_ROOTDIR
+ 2;
173 entry
.fid
.Unique
= DYNROOT_UNIQUE
;
176 ret
= cell_foreach (create_cell_entry_func
, &entry
);
180 ret
= cell_alias_foreach(create_alias_entry_func
, &entry
);
190 * for the `vnode' create apropriate symlink in `fbuf'
194 dynroot_create_symlink (fbuf
*fbuf
, int32_t vnode
)
198 int len
, ret
, rw
= 0;
200 cell
= cell_get_by_id (afs2cellnum (vnode
, &rw
));
204 len
= asprintf (&name
, "%c%s:root.cell.", rw
? '%' : '#', cell
->name
);
208 ret
= fbuf_truncate (fbuf
, len
);
210 memmove (fbuf_buf(fbuf
), name
, len
);
217 * Return TRUE if the combination `cell' and `volume' is
222 dynroot_isvolumep (int cell
, const char *volume
)
227 (strcmp (volume
, "root.afs") == 0
228 || strcmp (volume
, DYNROOT_ROOTVOLUME_STR
) == 0))
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
));
245 entry
->volumeId
[ROVOL
] = DYNROOT_ROOTVOLUME
;
246 entry
->flags
= VLF_ROEXISTS
;
252 * make sure `cred' is present in `entry'
255 dynroot_set_access(FCacheEntry
*entry
, nnpfs_pag_t cred
)
258 if (findaccess(cred
, entry
->acccache
, &ae
) == FALSE
) {
260 ae
->access
= entry
->status
.CallerAccess
;
265 * Update `entry' to contain the correct information
266 * Note: doesn't update status.Length and status.LinkCount
270 dynroot_update_entry (FCacheEntry
*entry
, int32_t filetype
,
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
;
285 entry
->status
.UnixModeBits
= 0755;
288 entry
->status
.UnixModeBits
= 0644;
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'
322 dynroot_get_node (FCacheEntry
*entry
, CredCacheEntry
*ce
)
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 */
336 ret
= abuf_create(&dir
, entry
, 0, FBUF_READ
| FBUF_WRITE
);
342 ret
= dynroot_create_root(&dir
, &nentries
);
343 entry
->status
.LinkCount
= nentries
;
345 ret
= dynroot_create_symlink (&dir
, entry
->fid
.fid
.Vnode
);
346 entry
->status
.LinkCount
= 1;
354 entry
->flags
.attrp
= TRUE
;
356 dynroot_update_entry (entry
, rootnode
? TYPE_DIR
: TYPE_LINK
,
360 fcache_mark_as_mountpoint (entry
);
362 len
= fbuf_len(&dir
);
363 fcache_set_have_all(entry
, len
);
365 ret
= abuf_end(&dir
);
369 entry
->tokens
|= NNPFS_ATTR_R
|NNPFS_DATA_R
;
371 last_celldb_version
= cell_get_version();
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.
402 dynroot_is_dynrootp (FCacheEntry
*entry
)
406 if (dynroot_enabled
&&
407 entry
->fid
.Cell
== DYNROOT_CELLID
&&
408 entry
->fid
.fid
.Volume
== DYNROOT_ROOTVOLUME
)
415 * Return what status the dynroot is in.
419 dynroot_enablep (void)
421 return dynroot_enabled
;
425 * Enable/Disable the dynroot depending on `enable', returns previous state.
429 dynroot_setenable (Bool enable
)
431 Bool was
= dynroot_enabled
;
432 dynroot_enabled
= enable
;
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
;