GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/amd/amd/nfs_subr.c Lines: 0 124 0.0 %
Date: 2017-11-07 Branches: 0 68 0.0 %

Line Branch Exec Source
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
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 *
34
 *	from: @(#)nfs_subr.c	8.1 (Berkeley) 6/6/93
35
 *	$Id: nfs_subr.c,v 1.9 2015/01/22 03:43:58 guenther Exp $
36
 */
37
38
#include "am.h"
39
40
/*
41
 * Convert from UN*X to NFS error code
42
 */
43
#ifdef NFS_ERROR_MAPPING
44
NFS_ERROR_MAPPING
45
#define nfs_error(e) \
46
        ((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
47
        nfs_errormap[(e) - NFS_LOMAP] : (e)))
48
#else
49
#define nfs_error(e) ((nfsstat)(e))
50
#endif /* NFS_ERROR_MAPPING */
51
52
static char *
53
do_readlink(am_node *mp, int *error_return, struct attrstat **attrpp)
54
{
55
	char *ln;
56
57
	/*
58
	 * If there is a readlink method, then use
59
	 * that, otherwise if a link exists use
60
	 * that, otherwise use the mount point.
61
	 */
62
	if (mp->am_mnt->mf_ops->readlink) {
63
		int retry = 0;
64
		mp = (*mp->am_mnt->mf_ops->readlink)(mp, &retry);
65
		if (mp == 0) {
66
			*error_return = retry;
67
			return 0;
68
		}
69
		/*reschedule_timeout_mp();*/
70
	}
71
	if (mp->am_link) {
72
		ln = mp->am_link;
73
	} else {
74
		ln = mp->am_mnt->mf_mount;
75
	}
76
	if (attrpp)
77
		*attrpp = &mp->am_attr;
78
	return ln;
79
}
80
81
void *
82
nfsproc_null_2_svc(void *argp, struct svc_req *rqstp)
83
{
84
	static char res;
85
86
	return &res;
87
}
88
89
90
struct attrstat *
91
nfsproc_getattr_2_svc(struct nfs_fh *argp, struct svc_req *rqstp)
92
{
93
	static struct attrstat res;
94
	am_node *mp;
95
	int retry;
96
97
#ifdef DEBUG
98
	Debug(D_TRACE)
99
		plog(XLOG_DEBUG, "gettattr:");
100
#endif /* DEBUG */
101
102
	mp = fh_to_mp2(argp, &retry);
103
	if (mp == 0) {
104
getattr_retry:
105
106
		if (retry < 0)
107
			return 0;
108
		res.status = nfs_error(retry);
109
	} else {
110
		struct attrstat *attrp = &mp->am_attr;
111
		if (mp->am_fattr.type == NFLNK) {
112
			/*
113
			 * Make sure we can read the link,
114
			 * and then determine the length.
115
			 */
116
			char *ln = do_readlink(mp, &retry, &attrp);
117
			if (ln == 0)
118
				goto getattr_retry;
119
		}
120
#ifdef DEBUG
121
		Debug(D_TRACE)
122
			plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, attrp->attrstat_u.attributes.size);
123
#endif /* DEBUG */
124
		mp->am_stats.s_getattr++;
125
		return attrp;
126
	}
127
128
	return &res;
129
}
130
131
132
struct attrstat *
133
nfsproc_setattr_2_svc(struct sattrargs *argp, struct svc_req *rqstp)
134
{
135
	static struct attrstat res;
136
137
	if (!fh_to_mp(&argp->file))
138
		res.status = nfs_error(ESTALE);
139
	else
140
		res.status = nfs_error(EROFS);
141
142
	return &res;
143
}
144
145
146
void *
147
nfsproc_root_2_svc(void *argp, struct svc_req *rqstp)
148
{
149
	static char res;
150
151
	return &res;
152
}
153
154
155
struct diropres *
156
nfsproc_lookup_2_svc(struct diropargs *argp, struct svc_req *rqstp)
157
{
158
	static struct diropres res;
159
	am_node *mp;
160
	int retry;
161
162
#ifdef DEBUG
163
	Debug(D_TRACE)
164
		plog(XLOG_DEBUG, "lookup:");
165
#endif /* DEBUG */
166
167
	mp = fh_to_mp2(&argp->dir, &retry);
168
	if (mp == 0) {
169
		if (retry < 0)
170
			return 0;
171
		res.status = nfs_error(retry);
172
	} else {
173
		int error;
174
		am_node *ap;
175
#ifdef DEBUG
176
		Debug(D_TRACE)
177
			plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->name);
178
#endif /* DEBUG */
179
		ap = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &error, VLOOK_CREATE);
180
		if (ap == 0) {
181
			if (error < 0) {
182
#ifdef DEBUG
183
				dlog("Not sending RPC reply");
184
#endif /* DEBUG */
185
				amd_stats.d_drops++;
186
				return 0;
187
			}
188
			res.status = nfs_error(error);
189
		} else {
190
			mp_to_fh(ap, &res.diropres_u.diropres.file);
191
			res.diropres_u.diropres.attributes = ap->am_fattr;
192
			res.status = NFS_OK;
193
		}
194
		mp->am_stats.s_lookup++;
195
		/*reschedule_timeout_mp();*/
196
	}
197
198
	return &res;
199
}
200
201
202
struct readlinkres *
203
nfsproc_readlink_2_svc(struct nfs_fh *argp, struct svc_req *rqstp)
204
{
205
	static struct readlinkres res;
206
	am_node *mp;
207
	int retry;
208
209
#ifdef DEBUG
210
	Debug(D_TRACE)
211
		plog(XLOG_DEBUG, "readlink:");
212
#endif /* DEBUG */
213
214
	mp = fh_to_mp2(argp, &retry);
215
	if (mp == 0) {
216
readlink_retry:
217
		if (retry < 0)
218
			return 0;
219
		res.status = nfs_error(retry);
220
	} else {
221
		char *ln = do_readlink(mp, &retry, (struct attrstat **) 0);
222
		if (ln == 0)
223
			goto readlink_retry;
224
		res.status = NFS_OK;
225
#ifdef DEBUG
226
		Debug(D_TRACE)
227
			if (ln)
228
				plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
229
#endif /* DEBUG */
230
		res.readlinkres_u.data = ln;
231
		mp->am_stats.s_readlink++;
232
	}
233
234
	return &res;
235
}
236
237
238
struct readres *
239
nfsproc_read_2_svc(struct readargs *argp, struct svc_req *rqstp)
240
{
241
	static struct readres res;
242
243
	bzero(&res, sizeof(res));
244
245
	res.status = nfs_error(EACCES);
246
247
	return &res;
248
}
249
250
251
void *
252
nfsproc_writecache_2_svc(void *argp, struct svc_req *rqstp)
253
{
254
	static char res;
255
256
	return &res;
257
}
258
259
260
struct attrstat *
261
nfsproc_write_2_svc(writeargs *argp, struct svc_req *rqstp)
262
{
263
	static struct attrstat res;
264
265
	if (!fh_to_mp(&argp->file))
266
		res.status = nfs_error(ESTALE);
267
	else
268
		res.status = nfs_error(EROFS);
269
270
	return &res;
271
}
272
273
274
struct diropres *
275
nfsproc_create_2_svc(createargs *argp, struct svc_req *rqstp)
276
{
277
	static struct diropres res;
278
279
	if (!fh_to_mp(&argp->where.dir))
280
		res.status = nfs_error(ESTALE);
281
	else
282
		res.status = nfs_error(EROFS);
283
284
	return &res;
285
}
286
287
288
static nfsstat *
289
unlink_or_rmdir(struct diropargs *argp, struct svc_req *rqstp,
290
    int unlinkp)
291
{
292
	static nfsstat res;
293
	int retry;
294
	/*mntfs *mf;*/
295
	am_node *mp = fh_to_mp3(&argp->dir, &retry, VLOOK_DELETE);
296
297
	if (mp == 0) {
298
		if (retry < 0)
299
			return 0;
300
		res = nfs_error(retry);
301
		goto out;
302
	}
303
	/*mf = mp->am_mnt;*/
304
	if (mp->am_fattr.type != NFDIR) {
305
		res = nfs_error(ENOTDIR);
306
		goto out;
307
	}
308
#ifdef DEBUG
309
	Debug(D_TRACE)
310
		plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->name);
311
#endif /* DEBUG */
312
	mp = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &retry, VLOOK_DELETE);
313
	if (mp == 0) {
314
		/*
315
		 * Ignore retries...
316
		 */
317
		if (retry < 0)
318
			retry = 0;
319
		/*
320
		 * Usual NFS workaround...
321
		 */
322
		else if (retry == ENOENT)
323
			retry = 0;
324
		res = nfs_error(retry);
325
	} else {
326
		forcibly_timeout_mp(mp);
327
		res = NFS_OK;
328
	}
329
330
out:
331
	return &res;
332
}
333
334
335
nfsstat *
336
nfsproc_remove_2_svc(struct diropargs *argp, struct svc_req *rqstp)
337
{
338
	return unlink_or_rmdir(argp, rqstp, TRUE);
339
}
340
341
nfsstat *
342
nfsproc_rename_2_svc(renameargs *argp, struct svc_req *rqstp)
343
{
344
	static nfsstat res;
345
	if (!fh_to_mp(&argp->from.dir) || !fh_to_mp(&argp->to.dir))
346
		res = nfs_error(ESTALE);
347
	/*
348
	 * If the kernel is doing clever things with referenced files
349
	 * then let it pretend...
350
	 */
351
	else if (strncmp(argp->to.name, ".nfs", 4) == 0)
352
		res = NFS_OK;
353
	/*
354
	 * otherwise a failure
355
	 */
356
	else
357
		res = nfs_error(EROFS);
358
	return &res;
359
}
360
361
362
nfsstat *
363
nfsproc_link_2_svc(linkargs *argp, struct svc_req *rqstp)
364
{
365
	static nfsstat res;
366
	if (!fh_to_mp(&argp->from) || !fh_to_mp(&argp->to.dir))
367
		res = nfs_error(ESTALE);
368
	else
369
		res = nfs_error(EROFS);
370
371
	return &res;
372
}
373
374
375
nfsstat *
376
nfsproc_symlink_2_svc(symlinkargs *argp, struct svc_req *rqstp)
377
{
378
	static nfsstat res;
379
	if (!fh_to_mp(&argp->from.dir))
380
		res = nfs_error(ESTALE);
381
	else
382
		res = nfs_error(EROFS);
383
384
	return &res;
385
}
386
387
388
struct diropres *
389
nfsproc_mkdir_2_svc(createargs *argp, struct svc_req *rqstp)
390
{
391
	static struct diropres res;
392
	if (!fh_to_mp(&argp->where.dir))
393
		res.status = nfs_error(ESTALE);
394
	else
395
		res.status = nfs_error(EROFS);
396
397
	return &res;
398
}
399
400
401
nfsstat *
402
nfsproc_rmdir_2_svc(struct diropargs *argp, struct svc_req *rqstp)
403
{
404
	return unlink_or_rmdir(argp, rqstp, FALSE);
405
}
406
407
408
struct readdirres *
409
nfsproc_readdir_2_svc(readdirargs *argp, struct svc_req *rqstp)
410
{
411
	static readdirres res;
412
	static entry e_res[MAX_READDIR_ENTRIES];
413
	am_node *mp;
414
	int retry;
415
416
#ifdef DEBUG
417
	Debug(D_TRACE)
418
		plog(XLOG_DEBUG, "readdir:");
419
#endif /* DEBUG */
420
421
	mp = fh_to_mp2(&argp->dir, &retry);
422
	if (mp == 0) {
423
		if (retry < 0)
424
			return 0;
425
		res.status = nfs_error(retry);
426
	} else {
427
#ifdef DEBUG
428
		Debug(D_TRACE)
429
			plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
430
#endif /* DEBUG */
431
		res.status = nfs_error((*mp->am_mnt->mf_ops->readdir)(mp, argp->cookie,
432
					&res.readdirres_u.reply, e_res, argp->count));
433
		mp->am_stats.s_readdir++;
434
	}
435
436
	return &res;
437
}
438
439
struct statfsres *
440
nfsproc_statfs_2_svc(struct nfs_fh *argp, struct svc_req *rqstp)
441
{
442
	static statfsres res;
443
	am_node *mp;
444
	int retry;
445
446
#ifdef DEBUG
447
	Debug(D_TRACE)
448
		plog(XLOG_DEBUG, "statfs:");
449
#endif /* DEBUG */
450
451
	mp = fh_to_mp2(argp, &retry);
452
	if (mp == 0) {
453
		if (retry < 0)
454
			return 0;
455
		res.status = nfs_error(retry);
456
	} else {
457
		statfsokres *fp;
458
#ifdef DEBUG
459
		Debug(D_TRACE)
460
			plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
461
#endif /* DEBUG */
462
		/*
463
		 * just return faked up file system information
464
		 */
465
466
		fp = &res.statfsres_u.reply;
467
468
		fp->tsize = 1024;
469
		fp->bsize = 4096;
470
		fp->blocks = 0;
471
		fp->bfree = 0;
472
		fp->bavail = 0;
473
474
		res.status = NFS_OK;
475
		mp->am_stats.s_statfs++;
476
	}
477
478
	return &res;
479
}