2 Copyright (C) 2003 - 2010 Chaskiel Grundman
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <afsconfig.h>
28 #include <afs/param.h>
34 #include <afs/vlserver.h>
35 #include <afs/vldbint.h>
37 #include "afscp_internal.h"
40 * Allocate and populate an afscp_venusfid struct from component parts
42 struct afscp_venusfid *
43 afscp_MakeFid(struct afscp_cell *cell, afs_uint32 volume,
44 afs_uint32 vnode, afs_uint32 unique)
46 struct afscp_venusfid *ret;
51 ret = malloc(sizeof(struct afscp_venusfid));
57 ret->fid.Volume = volume;
58 ret->fid.Vnode = vnode;
59 ret->fid.Unique = unique;
64 * Duplicate an existing afscp_venusfid struct
66 struct afscp_venusfid *
67 afscp_DupFid(const struct afscp_venusfid *in)
69 struct afscp_venusfid *ret;
71 ret = malloc(sizeof(struct afscp_venusfid));
77 ret->fid.Volume = in->fid.Volume;
78 ret->fid.Vnode = in->fid.Vnode;
79 ret->fid.Unique = in->fid.Unique;
84 afscp_FreeFid(struct afscp_venusfid *avfp)
91 statcompare(const void *a, const void *b)
93 const struct afscp_statent *sa = a, *sb = b;
94 if (sa->me.fid.Vnode < sb->me.fid.Vnode)
96 if (sa->me.fid.Vnode > sb->me.fid.Vnode)
98 if (sa->me.fid.Unique < sb->me.fid.Unique)
100 if (sa->me.fid.Unique > sb->me.fid.Unique)
106 afscp_GetStatus(const struct afscp_venusfid *fid, struct AFSFetchStatus *s)
108 struct afscp_volume *v;
109 struct afscp_server *server;
110 struct AFSCallBack cb;
111 struct AFSVolSync vs;
112 struct AFSFid tf = fid->fid;
113 struct afscp_statent *stored, key;
118 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
122 memset(&key, 0, sizeof(key));
123 memcpy(&key.me, fid, sizeof(*fid));
125 cached = tfind(&key, &v->statcache, statcompare);
126 if (cached != NULL) {
127 stored = *(struct afscp_statent **)cached;
128 memmove(s, &stored->status, sizeof(*s));
129 afs_dprintf(("Stat %u.%lu.%lu.%lu returning cached result\n",
130 fid->cell->id, fid->fid.Volume, fid->fid.Vnode,
136 for (i = 0; i < v->nservers; i++) {
137 server = afscp_ServerByIndex(v->servers[i]);
138 if (server && server->naddrs > 0) {
139 for (j = 0; j < server->naddrs; j++) {
141 code = RXAFS_FetchStatus(server->conns[j], &tf, s, &cb, &vs);
143 afscp_AddCallBack(server, &fid->fid, s, &cb, now); /* calls _StatStuff */
144 afs_dprintf(("Stat %d.%lu.%lu.%lu"
145 " ok: type %ld size %ld\n",
147 afs_printable_uint32_lu(fid->fid.Volume),
148 afs_printable_uint32_lu(fid->fid.Vnode),
149 afs_printable_uint32_lu(fid->fid.Unique),
150 afs_printable_int32_ld(s->FileType),
151 afs_printable_int32_ld(s->Length)));
162 afscp_Stat(const struct afscp_venusfid *fid, struct stat *s)
165 struct AFSFetchStatus status;
169 if (s == NULL || fid == NULL) {
170 fprintf(stderr, "NULL args given to afscp_Stat, cannot continue\n");
174 code = afscp_GetStatus(fid, &status);
179 if (status.FileType == File)
180 s->st_mode = S_IFREG;
181 else if (status.FileType == Directory)
182 s->st_mode = S_IFDIR;
184 else if (status.FileType == SymbolicLink)
185 s->st_mode = S_IFLNK;
186 /* a behavior needs to be defined on Windows */
189 afscp_errno = EINVAL;
192 s->st_mode |= (status.UnixModeBits & (~S_IFMT));
193 s->st_nlink = status.LinkCount;
194 s->st_size = status.Length;
195 s->st_uid = status.Owner;
196 /*s->st_blksize=status.SegSize; */
197 s->st_atime = s->st_mtime = status.ClientModTime;
198 s->st_ctime = status.ServerModTime;
199 s->st_gid = status.Group;
204 _StatInvalidate(const struct afscp_venusfid *fid)
206 struct afscp_volume *v;
207 struct afscp_statent key;
210 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
214 memmove(&key.me, fid, sizeof(*fid));
216 cached = tfind(&key, &v->statcache, statcompare);
217 if (cached != NULL) {
219 tdelete(&key, &v->statcache, statcompare);
225 _StatStuff(const struct afscp_venusfid *fid, const struct AFSFetchStatus *s)
227 struct afscp_volume *v;
228 struct afscp_statent key, *stored;
231 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
235 memmove(&key.me, fid, sizeof(*fid));
237 cached = tsearch(&key, &v->statcache, statcompare);
238 if (cached != NULL) {
239 stored = malloc(sizeof(struct afscp_statent));
240 if (stored != NULL) {
241 memmove(&stored->me, fid, sizeof(*fid));
242 memmove(&stored->status, s, sizeof(*s));
243 *(struct afscp_statent **)cached = stored;
245 tdelete(&key, &v->statcache, statcompare);
252 afscp_StoreStatus(const struct afscp_venusfid *fid, struct AFSStoreStatus *s)
254 struct afscp_volume *v;
255 struct afscp_server *server;
256 struct AFSVolSync vs;
257 struct AFSFetchStatus fst;
258 struct AFSFid tf = fid->fid;
261 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
267 for (i = 0; i < v->nservers; i++) {
268 server = afscp_ServerByIndex(v->servers[i]);
269 if (server && server->naddrs > 0) {
270 for (j = 0; j < server->naddrs; j++) {
271 code = RXAFS_StoreStatus(server->conns[j], &tf, s, &fst, &vs);
273 _StatStuff(fid, &fst); /* calls _StatStuff */