xref: /original-bsd/usr.sbin/amd/amd/nfs_subr.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1990 Jan-Simon Pendry
3  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4  * Copyright (c) 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Jan-Simon Pendry at Imperial College, London.
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)nfs_subr.c	8.1 (Berkeley) 06/06/93
13  *
14  * $Id: nfs_subr.c,v 5.2.2.1 1992/02/09 15:08:53 jsp beta $
15  *
16  */
17 
18 #include "am.h"
19 
20 /*
21  * Convert from UN*X to NFS error code
22  */
23 #ifdef NFS_ERROR_MAPPING
24 NFS_ERROR_MAPPING
25 #define nfs_error(e) \
26         ((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
27         nfs_errormap[(e) - NFS_LOMAP] : (e)))
28 #else
29 #define nfs_error(e) ((nfsstat)(e))
30 #endif /* NFS_ERROR_MAPPING */
31 
32 static char *do_readlink P((am_node *mp, int *error_return, struct attrstat **attrpp));
33 static char *do_readlink(mp, error_return, attrpp)
34 am_node *mp;
35 int *error_return;
36 struct attrstat **attrpp;
37 {
38 	char *ln;
39 
40 	/*
41 	 * If there is a readlink method, then use
42 	 * that, otherwise if a link exists use
43 	 * that, otherwise use the mount point.
44 	 */
45 	if (mp->am_mnt->mf_ops->readlink) {
46 		int retry = 0;
47 		mp = (*mp->am_mnt->mf_ops->readlink)(mp, &retry);
48 		if (mp == 0) {
49 			*error_return = retry;
50 			return 0;
51 		}
52 		/*reschedule_timeout_mp();*/
53 	}
54 	if (mp->am_link) {
55 		ln = mp->am_link;
56 	} else {
57 		ln = mp->am_mnt->mf_mount;
58 	}
59 	if (attrpp)
60 		*attrpp = &mp->am_attr;
61 	return ln;
62 }
63 
64 /*ARGSUSED*/
65 voidp
66 nfsproc_null_2(argp, rqstp)
67 voidp argp;
68 struct svc_req *rqstp;
69 {
70 	static char res;
71 
72 	return (voidp) &res;
73 }
74 
75 
76 /*ARGSUSED*/
77 struct attrstat *
78 nfsproc_getattr_2(argp, rqstp)
79 struct nfs_fh *argp;
80 struct svc_req *rqstp;
81 {
82 	static struct attrstat res;
83 	am_node *mp;
84 	int retry;
85 
86 #ifdef DEBUG
87 	Debug(D_TRACE)
88 		plog(XLOG_DEBUG, "gettattr:");
89 #endif /* DEBUG */
90 
91 	mp = fh_to_mp2(argp, &retry);
92 	if (mp == 0) {
93 #ifdef PRECISE_SYMLINKS
94 getattr_retry:
95 #endif /* PRECISE_SYMLINKS */
96 
97 		if (retry < 0)
98 			return 0;
99 		res.status = nfs_error(retry);
100 	} else {
101 		struct attrstat *attrp = &mp->am_attr;
102 #ifdef PRECISE_SYMLINKS
103 		if (mp->am_fattr.type == NFLNK) {
104 			/*
105 			 * Make sure we can read the link,
106 			 * and then determine the length.
107 			 */
108 			char *ln = do_readlink(mp, &retry, &attrp);
109 			if (ln == 0)
110 				goto getattr_retry;
111 		}
112 #endif /* PRECISE_SYMLINKS */
113 #ifdef DEBUG
114 		Debug(D_TRACE)
115 			plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, attrp->attrstat_u.attributes.size);
116 #endif /* DEBUG */
117 		mp->am_stats.s_getattr++;
118 		return attrp;
119 	}
120 
121 	return &res;
122 }
123 
124 
125 /*ARGSUSED*/
126 struct attrstat *
127 nfsproc_setattr_2(argp, rqstp)
128 struct sattrargs *argp;
129 struct svc_req *rqstp;
130 {
131 	static struct attrstat res;
132 
133 	if (!fh_to_mp(&argp->file))
134 		res.status = nfs_error(ESTALE);
135 	else
136 		res.status = nfs_error(EROFS);
137 
138 	return &res;
139 }
140 
141 
142 /*ARGSUSED*/
143 voidp
144 nfsproc_root_2(argp, rqstp)
145 voidp argp;
146 struct svc_req *rqstp;
147 {
148 	static char res;
149 
150 	return (voidp)&res;
151 }
152 
153 
154 /*ARGSUSED*/
155 struct diropres *
156 nfsproc_lookup_2(argp, rqstp)
157 struct diropargs *argp;
158 struct svc_req *rqstp;
159 {
160 	static struct diropres res;
161 	am_node *mp;
162 	int retry;
163 
164 #ifdef DEBUG
165 	Debug(D_TRACE)
166 		plog(XLOG_DEBUG, "lookup:");
167 #endif /* DEBUG */
168 
169 	mp = fh_to_mp2(&argp->dir, &retry);
170 	if (mp == 0) {
171 		if (retry < 0)
172 			return 0;
173 		res.status = nfs_error(retry);
174 	} else {
175 		int error;
176 		am_node *ap;
177 #ifdef DEBUG
178 		Debug(D_TRACE)
179 			plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->name);
180 #endif /* DEBUG */
181 		ap = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &error, VLOOK_CREATE);
182 		if (ap == 0) {
183 			if (error < 0) {
184 #ifdef DEBUG
185 				dlog("Not sending RPC reply");
186 #endif /* DEBUG */
187 				amd_stats.d_drops++;
188 				return 0;
189 			}
190 			res.status = nfs_error(error);
191 		} else {
192 			mp_to_fh(ap, &res.diropres_u.diropres.file);
193 			res.diropres_u.diropres.attributes = ap->am_fattr;
194 			res.status = NFS_OK;
195 		}
196 		mp->am_stats.s_lookup++;
197 		/*reschedule_timeout_mp();*/
198 	}
199 
200 	return &res;
201 }
202 
203 
204 /*ARGSUSED*/
205 struct readlinkres *
206 nfsproc_readlink_2(argp, rqstp)
207 struct nfs_fh *argp;
208 struct svc_req *rqstp;
209 {
210 	static struct readlinkres res;
211 	am_node *mp;
212 	int retry;
213 
214 #ifdef DEBUG
215 	Debug(D_TRACE)
216 		plog(XLOG_DEBUG, "readlink:");
217 #endif /* DEBUG */
218 
219 	mp = fh_to_mp2(argp, &retry);
220 	if (mp == 0) {
221 readlink_retry:
222 		if (retry < 0)
223 			return 0;
224 		res.status = nfs_error(retry);
225 	} else {
226 		char *ln = do_readlink(mp, &retry, (struct attrstat **) 0);
227 		if (ln == 0)
228 			goto readlink_retry;
229 		res.status = NFS_OK;
230 #ifdef DEBUG
231 		Debug(D_TRACE)
232 			if (ln)
233 				plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
234 #endif /* DEBUG */
235 		res.readlinkres_u.data = ln;
236 		mp->am_stats.s_readlink++;
237 	}
238 
239 	return &res;
240 }
241 
242 
243 /*ARGSUSED*/
244 struct readres *
245 nfsproc_read_2(argp, rqstp)
246 struct readargs *argp;
247 struct svc_req *rqstp;
248 {
249 	static struct readres res;
250 
251 	bzero((char *)&res, sizeof(res));
252 
253 	res.status = nfs_error(EACCES);
254 
255 	return &res;
256 }
257 
258 
259 /*ARGSUSED*/
260 voidp
261 nfsproc_writecache_2(argp, rqstp)
262 voidp argp;
263 struct svc_req *rqstp;
264 {
265 	static char res;
266 
267 	return (voidp) &res;
268 }
269 
270 
271 /*ARGSUSED*/
272 struct attrstat *
273 nfsproc_write_2(argp, rqstp)
274 writeargs *argp;
275 struct svc_req *rqstp;
276 {
277 	static struct attrstat res;
278 
279 	if (!fh_to_mp(&argp->file))
280 		res.status = nfs_error(ESTALE);
281 	else
282 		res.status = nfs_error(EROFS);
283 
284 	return &res;
285 }
286 
287 
288 /*ARGSUSED*/
289 struct diropres *
290 nfsproc_create_2(argp, rqstp)
291 createargs *argp;
292 struct svc_req *rqstp;
293 {
294 	static struct diropres res;
295 
296 	if (!fh_to_mp(&argp->where.dir))
297 		res.status = nfs_error(ESTALE);
298 	else
299 		res.status = nfs_error(EROFS);
300 
301 	return &res;
302 }
303 
304 
305 /*ARGSUSED*/
306 static nfsstat *
307 unlink_or_rmdir(argp, rqstp, unlinkp)
308 struct diropargs *argp;
309 struct svc_req *rqstp;
310 int unlinkp;
311 {
312 	static nfsstat res;
313 	int retry;
314 	/*mntfs *mf;*/
315 	am_node *mp = fh_to_mp3(&argp->dir, &retry, VLOOK_DELETE);
316 	if (mp == 0) {
317 		if (retry < 0)
318 			return 0;
319 		res = nfs_error(retry);
320 		goto out;
321 	}
322 	/*mf = mp->am_mnt;*/
323 	if (mp->am_fattr.type != NFDIR) {
324 		res = nfs_error(ENOTDIR);
325 		goto out;
326 	}
327 #ifdef DEBUG
328 	Debug(D_TRACE)
329 		plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->name);
330 #endif /* DEBUG */
331 	mp = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &retry, VLOOK_DELETE);
332 	if (mp == 0) {
333 		/*
334 		 * Ignore retries...
335 		 */
336 		if (retry < 0)
337 			retry = 0;
338 		/*
339 		 * Usual NFS workaround...
340 		 */
341 		else if (retry == ENOENT)
342 			retry = 0;
343 		res = nfs_error(retry);
344 	} else {
345 		forcibly_timeout_mp(mp);
346 		res = NFS_OK;
347 	}
348 
349 out:
350 	return &res;
351 }
352 
353 
354 /*ARGSUSED*/
355 nfsstat *
356 nfsproc_remove_2(argp, rqstp)
357 struct diropargs *argp;
358 struct svc_req *rqstp;
359 {
360 	return unlink_or_rmdir(argp, rqstp, TRUE);
361 }
362 
363 /*ARGSUSED*/
364 nfsstat *
365 nfsproc_rename_2(argp, rqstp)
366 renameargs *argp;
367 struct svc_req *rqstp;
368 {
369 	static nfsstat res;
370 	if (!fh_to_mp(&argp->from.dir) || !fh_to_mp(&argp->to.dir))
371 		res = nfs_error(ESTALE);
372 	/*
373 	 * If the kernel is doing clever things with referenced files
374 	 * then let it pretend...
375 	 */
376 	else if (strncmp(argp->to.name, ".nfs", 4) == 0)
377 		res = NFS_OK;
378 	/*
379 	 * otherwise a failure
380 	 */
381 	else
382 		res = nfs_error(EROFS);
383 	return &res;
384 }
385 
386 
387 /*ARGSUSED*/
388 nfsstat *
389 nfsproc_link_2(argp, rqstp)
390 linkargs *argp;
391 struct svc_req *rqstp;
392 {
393 	static nfsstat res;
394 	if (!fh_to_mp(&argp->from) || !fh_to_mp(&argp->to.dir))
395 		res = nfs_error(ESTALE);
396 	else
397 		res = nfs_error(EROFS);
398 
399 	return &res;
400 }
401 
402 
403 /*ARGSUSED*/
404 nfsstat *
405 nfsproc_symlink_2(argp, rqstp)
406 symlinkargs *argp;
407 struct svc_req *rqstp;
408 {
409 	static nfsstat res;
410 	if (!fh_to_mp(&argp->from.dir))
411 		res = nfs_error(ESTALE);
412 	else
413 		res = nfs_error(EROFS);
414 
415 	return &res;
416 }
417 
418 
419 /*ARGSUSED*/
420 struct diropres *
421 nfsproc_mkdir_2(argp, rqstp)
422 createargs *argp;
423 struct svc_req *rqstp;
424 {
425 	static struct diropres res;
426 	if (!fh_to_mp(&argp->where.dir))
427 		res.status = nfs_error(ESTALE);
428 	else
429 		res.status = nfs_error(EROFS);
430 
431 	return &res;
432 }
433 
434 
435 /*ARGSUSED*/
436 nfsstat *
437 nfsproc_rmdir_2(argp, rqstp)
438 struct diropargs *argp;
439 struct svc_req *rqstp;
440 {
441 	return unlink_or_rmdir(argp, rqstp, FALSE);
442 }
443 
444 
445 /*ARGSUSED*/
446 struct readdirres *
447 nfsproc_readdir_2(argp, rqstp)
448 readdirargs *argp;
449 struct svc_req *rqstp;
450 {
451 	static readdirres res;
452 	static entry e_res[MAX_READDIR_ENTRIES];
453 	am_node *mp;
454 	int retry;
455 
456 #ifdef DEBUG
457 	Debug(D_TRACE)
458 		plog(XLOG_DEBUG, "readdir:");
459 #endif /* DEBUG */
460 
461 	mp = fh_to_mp2(&argp->dir, &retry);
462 	if (mp == 0) {
463 		if (retry < 0)
464 			return 0;
465 		res.status = nfs_error(retry);
466 	} else {
467 #ifdef DEBUG
468 		Debug(D_TRACE)
469 			plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
470 #endif /* DEBUG */
471 		res.status = nfs_error((*mp->am_mnt->mf_ops->readdir)(mp, argp->cookie,
472 					&res.readdirres_u.reply, e_res, argp->count));
473 		mp->am_stats.s_readdir++;
474 	}
475 
476 	return &res;
477 }
478 
479 /*ARGSUSED*/
480 struct statfsres *
481 nfsproc_statfs_2(argp, rqstp)
482 struct nfs_fh *argp;
483 struct svc_req *rqstp;
484 {
485 	static statfsres res;
486 	am_node *mp;
487 	int retry;
488 
489 #ifdef DEBUG
490 	Debug(D_TRACE)
491 		plog(XLOG_DEBUG, "statfs:");
492 #endif /* DEBUG */
493 
494 	mp = fh_to_mp2(argp, &retry);
495 	if (mp == 0) {
496 		if (retry < 0)
497 			return 0;
498 		res.status = nfs_error(retry);
499 	} else {
500 		statfsokres *fp;
501 #ifdef DEBUG
502 		Debug(D_TRACE)
503 			plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
504 #endif /* DEBUG */
505 		/*
506 		 * just return faked up file system information
507 		 */
508 
509 		fp = &res.statfsres_u.reply;
510 
511 		fp->tsize = 1024;
512 		fp->bsize = 4096;
513 #ifdef HAS_EMPTY_AUTOMOUNTS
514 		fp->blocks = 0;
515 #else
516 		fp->blocks = 1;
517 #endif
518 		fp->bfree = 0;
519 		fp->bavail = 0;
520 
521 		res.status = NFS_OK;
522 		mp->am_stats.s_statfs++;
523 	}
524 
525 	return &res;
526 }
527