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