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