Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / libafscp / afscp_dirops.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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.
15
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.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <afs/vlserver.h>
33 #include <afs/vldbint.h>
34 #include <afs/dir.h>
35 #include <afs/unified_afs.h>
36 #include "afscp.h"
37 #include "afscp_internal.h"
38
39 int
40 afscp_CreateFile(const struct afscp_venusfid *dir, char *name,
41 struct AFSStoreStatus *sst, struct afscp_venusfid **ret)
42 {
43 int code, i, j;
44 struct AFSFid df = dir->fid;
45 struct afscp_volume *vol;
46 struct AFSFetchStatus dfst, fst;
47 struct AFSVolSync vs;
48 struct AFSCallBack cb;
49 struct AFSFid ff;
50 struct afscp_server *server;
51 struct rx_connection *c;
52 time_t now;
53
54 if (dir == NULL || name == NULL || sst == NULL) {
55 fprintf(stderr,
56 "afscp_CreateFile called with NULL args, cannot continue\n");
57 return -1;
58 }
59 vol = afscp_VolumeById(dir->cell, dir->fid.Volume);
60 if (vol == NULL) {
61 afscp_errno = ENOENT;
62 return -1;
63 }
64 code = ENOENT;
65 for (i = 0; i < vol->nservers; i++) {
66 server = afscp_ServerByIndex(vol->servers[i]);
67 if (server && server->naddrs > 0) {
68 for (j = 0; j < server->naddrs; j++) {
69 c = afscp_ServerConnection(server, j);
70 if (c == NULL) {
71 break;
72 }
73 time(&now);
74 code = RXAFS_CreateFile(c, &df, name, sst, &ff,
75 &fst, &dfst, &cb, &vs);
76 if (code >= 0) {
77 break;
78 }
79 }
80 }
81 if (code >= 0) {
82 break;
83 }
84 }
85 if (code != 0) {
86 _StatInvalidate(dir);
87 afscp_errno = code;
88 return -1;
89 }
90 _StatStuff(dir, &dfst);
91 afscp_AddCallBack(server, &ff, &fst, &cb, now);
92 if (ret != NULL)
93 *ret = afscp_MakeFid(vol->cell, ff.Volume, ff.Vnode, ff.Unique);
94 return 0;
95 }
96
97 int
98 afscp_MakeDir(const struct afscp_venusfid *dir, char *name,
99 struct AFSStoreStatus *sst, struct afscp_venusfid **ret)
100 {
101 int code, i, j;
102 struct AFSFid df = dir->fid;
103 struct afscp_volume *vol;
104 struct AFSFetchStatus dfst, fst;
105 struct AFSVolSync vs;
106 struct AFSCallBack cb;
107 struct AFSFid ff;
108 struct afscp_server *server;
109 struct rx_connection *c;
110 time_t now;
111
112 vol = afscp_VolumeById(dir->cell, dir->fid.Volume);
113 if (vol == NULL) {
114 afscp_errno = ENOENT;
115 return -1;
116 }
117 code = ENOENT;
118 for (i = 0; i < vol->nservers; i++) {
119 server = afscp_ServerByIndex(vol->servers[i]);
120 if (server && server->naddrs > 0) {
121 for (j = 0; j < server->naddrs; j++) {
122 c = afscp_ServerConnection(server, j);
123 if (c == NULL)
124 break;
125 time(&now);
126 code = RXAFS_MakeDir(c, &df, name, sst, &ff,
127 &fst, &dfst, &cb, &vs);
128 if (code >= 0)
129 break;
130 }
131 }
132 if (code >= 0)
133 break;
134 }
135 if (code != 0) {
136 _StatInvalidate(dir);
137 afscp_errno = code;
138 return -1;
139 }
140 _StatStuff(dir, &dfst);
141 afscp_AddCallBack(server, &ff, &fst, &cb, now);
142 if (ret != NULL)
143 *ret = afscp_MakeFid(vol->cell, ff.Volume, ff.Vnode, ff.Unique);
144 return 0;
145 }
146
147 int
148 afscp_Symlink(const struct afscp_venusfid *dir, char *name,
149 char *target, struct AFSStoreStatus *sst)
150 {
151 int code, i, j;
152 struct AFSFid df = dir->fid;
153 struct afscp_volume *vol;
154 struct AFSFetchStatus dfst, fst;
155 struct AFSVolSync vs;
156 struct AFSFid ff;
157 struct afscp_server *server;
158 struct rx_connection *c;
159
160 vol = afscp_VolumeById(dir->cell, dir->fid.Volume);
161 if (vol == NULL) {
162 afscp_errno = ENOENT;
163 return -1;
164 }
165 code = ENOENT;
166 for (i = 0; i < vol->nservers; i++) {
167 server = afscp_ServerByIndex(vol->servers[i]);
168 if (server && server->naddrs > 0) {
169 for (j = 0; j < server->naddrs; j++) {
170 c = afscp_ServerConnection(server, j);
171 if (c == NULL)
172 break;
173 code = RXAFS_Symlink(c, &df, name, target, sst,
174 &ff, &fst, &dfst, &vs);
175 if (code >= 0)
176 break;
177 }
178 }
179 if (code >= 0)
180 break;
181 }
182 if (code != 0) {
183 _StatInvalidate(dir);
184 afscp_errno = code;
185 return -1;
186 }
187 _StatStuff(dir, &dfst);
188 return 0;
189 }
190
191
192 int
193 afscp_Lock(const struct afscp_venusfid *fid, int locktype)
194 {
195 int code, i, j;
196 struct AFSFid ff = fid->fid;
197 struct afscp_volume *vol;
198 struct AFSVolSync vs;
199 struct afscp_server *server;
200 struct rx_connection *c;
201
202 vol = afscp_VolumeById(fid->cell, fid->fid.Volume);
203 if (vol == NULL) {
204 afscp_errno = ENOENT;
205 return -1;
206 }
207 code = ENOENT;
208 for (i = 0; i < vol->nservers; i++) {
209 server = afscp_ServerByIndex(vol->servers[i]);
210 if (server && server->naddrs > 0) {
211 for (j = 0; j < server->naddrs; j++) {
212 c = afscp_ServerConnection(server, j);
213 if (c == NULL)
214 break;
215 if (locktype == LockRelease)
216 code = RXAFS_ReleaseLock(c, &ff, &vs);
217 /* read, write, extend */
218 else if (locktype < LockRelease)
219 code = RXAFS_SetLock(c, &ff, locktype, &vs);
220 if (code >= 0)
221 break;
222 }
223 }
224 if (code >= 0)
225 break;
226 }
227 if (code != 0) {
228 if ((code == EAGAIN) || (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
229 code = EWOULDBLOCK;
230 afscp_errno = code;
231 return -1;
232 }
233 return 0;
234 }
235
236
237 int
238 afscp_RemoveFile(const struct afscp_venusfid *dir, char *name)
239 {
240 int code, i, j;
241 struct AFSFid df = dir->fid;
242 struct afscp_volume *vol;
243 struct AFSFetchStatus dfst;
244 struct AFSVolSync vs;
245 struct afscp_server *server;
246 struct rx_connection *c;
247
248 vol = afscp_VolumeById(dir->cell, dir->fid.Volume);
249 if (vol == NULL) {
250 afscp_errno = ENOENT;
251 return -1;
252 }
253 code = ENOENT;
254 for (i = 0; i < vol->nservers; i++) {
255 server = afscp_ServerByIndex(vol->servers[i]);
256 if (server && server->naddrs > 0) {
257 for (j = 0; j < server->naddrs; j++) {
258 c = afscp_ServerConnection(server, j);
259 if (c == NULL)
260 break;
261 code = RXAFS_RemoveFile(c, &df, name, &dfst, &vs);
262 if (code >= 0)
263 break;
264 }
265 }
266 if (code >= 0)
267 break;
268 }
269 if (code != 0) {
270 _StatInvalidate(dir);
271 afscp_errno = code;
272 return -1;
273 }
274 _StatStuff(dir, &dfst);
275 return 0;
276 }
277
278 int
279 afscp_RemoveDir(const struct afscp_venusfid *dir, char *name)
280 {
281 int code, i, j;
282 struct AFSFid df = dir->fid;
283 struct afscp_volume *vol;
284 struct AFSFetchStatus dfst;
285 struct AFSVolSync vs;
286 struct afscp_server *server;
287 struct rx_connection *c;
288
289 vol = afscp_VolumeById(dir->cell, dir->fid.Volume);
290 if (vol == NULL) {
291 afscp_errno = ENOENT;
292 return -1;
293 }
294 code = ENOENT;
295 for (i = 0; i < vol->nservers; i++) {
296 server = afscp_ServerByIndex(vol->servers[i]);
297 if (server && server->naddrs > 0) {
298 for (j = 0; j < server->naddrs; j++) {
299 c = afscp_ServerConnection(server, j);
300 if (c == NULL)
301 break;
302 code = RXAFS_RemoveDir(c, &df, name, &dfst, &vs);
303 if (code >= 0)
304 break;
305 }
306 }
307 if (code >= 0)
308 break;
309 }
310 if (code != 0) {
311 _StatInvalidate(dir);
312 afscp_errno = code;
313 return -1;
314 }
315 _StatStuff(dir, &dfst);
316 return 0;
317 }