Bug Summary

File:obj-scan-build/nfsd/../../nfsd/ops.c
Location:line 398, column 3
Description:Value stored to 'err' is never read

Annotated Source Code

1/* ops.c NFS daemon protocol operations.
2
3 Copyright (C) 1996, 2001, 2002, 2007 Free Software Foundation, Inc.
4
5 Written by Michael I. Bushnell, p/BSG.
6
7 This file is part of the GNU Hurd.
8
9 The GNU Hurd is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
13
14 The GNU Hurd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
22
23#include <hurd/io.h>
24#include <hurd/fs.h>
25#include <fcntl.h>
26#include <hurd/paths.h>
27#include <hurd.h>
28#include <dirent.h>
29#include <string.h>
30#include <sys/mman.h>
31
32#include "nfsd.h"
33#include "../nfs/mount.h" /* XXX */
34#include <rpc/pmap_prot.h>
35
36static error_t
37op_null (struct cache_handle *c,
38 int *p,
39 int **reply,
40 int version)
41{
42 return 0;
43}
44
45static error_t
46op_getattr (struct cache_handle *c,
47 int *p,
48 int **reply,
49 int version)
50{
51 struct stat st;
52 error_t err;
53
54 err = io_stat (c->port, &st);
55 if (!err)
56 *reply = encode_fattr (*reply, &st, version);
57 return err;
58}
59
60static error_t
61complete_setattr (mach_port_t port,
62 int *p)
63{
64 uid_t uid, gid;
65 off_t size;
66 time_value_t atime, mtime;
67 struct stat st;
68 error_t err;
69
70 err = io_stat (port, &st);
71 if (err)
72 return err;
73
74 uid = ntohl (*p);
75 p++;
76 gid = ntohl (*p);
77 p++;
78 if (uid == -1)
79 uid = st.st_uid;
80 if (gid == -1)
81 gid = st.st_gid;
82 if (uid != st.st_uid || gid != st.st_gid)
83 err = file_chown (port, uid, gid);
84 if (err)
85 return err;
86
87 size = ntohl (*p);
88 p++;
89 if (size != -1 && size != st.st_size)
90 err = file_set_size (port, size);
91 if (err)
92 return err;
93
94 atime.seconds = ntohl (*p);
95 p++;
96 atime.microseconds = ntohl (*p);
97 p++;
98 mtime.seconds = ntohl (*p);
99 p++;
100 mtime.microseconds = ntohl (*p);
101 p++;
102
103 if (atime.seconds != -1 && atime.microseconds == -1)
104 atime.microseconds = 0;
105 if (mtime.seconds != -1 && mtime.microseconds == -1)
106 mtime.microseconds = 0;
107
108 if (atime.seconds == -1)
109 atime.seconds = st.st_atim.tv_sec;
110 if (atime.microseconds == -1)
111 atime.microseconds = st.st_atim.tv_nsec / 1000;
112 if (mtime.seconds == -1)
113 mtime.seconds = st.st_mtim.tv_sec;
114 if (mtime.microseconds == -1)
115 mtime.microseconds = st.st_mtim.tv_nsec / 1000;
116
117 if (atime.seconds != st.st_atim.tv_sec
118 || atime.microseconds != st.st_atim.tv_nsec / 1000
119 || mtime.seconds != st.st_mtim.tv_sec
120 || mtime.microseconds != st.st_mtim.tv_nsec / 1000)
121 err = file_utimes (port, atime, mtime);
122
123 return err;
124}
125
126static error_t
127op_setattr (struct cache_handle *c,
128 int *p,
129 int **reply,
130 int version)
131{
132 error_t err = 0;
133 mode_t mode;
134 struct stat st;
135
136 mode = ntohl (*p);
137 p++;
138 if (mode != -1)
139 err = file_chmod (c->port, mode);
140
141 if (!err)
142 err = complete_setattr (c->port, p);
143 if (!err)
144 err = io_stat (c->port, &st);
145 if (err)
146 return err;
147
148 *reply = encode_fattr (*reply, &st, version);
149 return 0;
150}
151
152static error_t
153op_lookup (struct cache_handle *c,
154 int *p,
155 int **reply,
156 int version)
157{
158 error_t err;
159 char *name;
160 retry_type do_retry;
161 char retry_name [1024];
162 mach_port_t newport;
163 struct cache_handle *newc;
164 struct stat st;
165
166 decode_name (p, &name);
167
168 err = dir_lookup (c->port, name, O_NOTRANS0x0080, 0, &do_retry, retry_name,
169 &newport);
170 free (name);
171
172 /* Block attempts to bounce out of this filesystem by any technique. */
173 if (!err
174 && (do_retry != FS_RETRY_NORMAL
175 || retry_name[0] != '\0'))
176 err = EACCES((0x10 << 26) | ((13) & 0x3fff));
177
178 if (!err)
179 err = io_stat (newport, &st);
180
181 if (err)
182 return err;
183
184 newc = create_cached_handle (*(int *)c->handle, c, newport);
185 if (!newc)
186 return ESTALE((0x10 << 26) | ((70) & 0x3fff));
187 *reply = encode_fhandle (*reply, newc->handle);
188 *reply = encode_fattr (*reply, &st, version);
189 return 0;
190}
191
192static error_t
193op_readlink (struct cache_handle *c,
194 int *p,
195 int **reply,
196 int version)
197{
198 char buf[2048], *transp = buf;
199 mach_msg_type_number_t len = sizeof (buf);
200 error_t err;
201
202 /* Shamelessly copied from the libc readlink. */
203 err = file_get_translator (c->port, &transp, &len);
204 if (err)
205 {
206 if (transp != buf)
207 munmap (transp, len);
208 return err;
209 }
210
211 if (len < sizeof (_HURD_SYMLINK"/hurd/" "symlink")
212 || memcmp (transp, _HURD_SYMLINK"/hurd/" "symlink", sizeof (_HURD_SYMLINK"/hurd/" "symlink")))
213 return EINVAL((0x10 << 26) | ((22) & 0x3fff));
214
215 transp += sizeof (_HURD_SYMLINK"/hurd/" "symlink");
216
217 *reply = encode_string (*reply, transp);
218
219 if (transp != buf)
220 munmap (transp, len);
221
222 return 0;
223}
224
225static size_t
226count_read_buffersize (int *p, int version)
227{
228 p++; /* Skip OFFSET. */
229 return ntohl (*p); /* Return COUNT. */
230}
231
232static error_t
233op_read (struct cache_handle *c,
234 int *p,
235 int **reply,
236 int version)
237{
238 off_t offset;
239 size_t count;
240 char buf[2048], *bp = buf;
241 mach_msg_type_number_t buflen = sizeof (buf);
242 struct stat st;
243 error_t err;
244
245 offset = ntohl (*p);
246 p++;
247 count = ntohl (*p);
248 p++;
249
250 err = io_read (c->port, &bp, &buflen, offset, count);
251 if (err)
252 {
253 if (bp != buf)
254 munmap (bp, buflen);
255 return err;
256 }
257
258 err = io_stat (c->port, &st);
259 if (err)
260 return err;
261
262 *reply = encode_fattr (*reply, &st, version);
263 *reply = encode_data (*reply, bp, buflen);
264
265 if (bp != buf)
266 munmap (bp, buflen);
267
268 return 0;
269}
270
271static error_t
272op_write (struct cache_handle *c,
273 int *p,
274 int **reply,
275 int version)
276{
277 off_t offset;
278 size_t count;
279 error_t err;
280 mach_msg_type_number_t amt;
281 char *bp;
282 struct stat st;
283
284 p++;
285 offset = ntohl (*p);
286 p++;
287 p++;
288 count = ntohl (*p);
289 p++;
290 bp = (char *) *reply;
291
292 while (count)
293 {
294 err = io_write (c->port, bp, count, offset, &amt);
295 if (err)
296 return err;
297 if (amt == 0)
298 return EIO((0x10 << 26) | ((5) & 0x3fff));
299 count -= amt;
300 bp += amt;
301 offset += amt;
302 }
303
304 file_sync (c->port, 1, 0);
305
306 err = io_stat (c->port, &st);
307 if (err)
308 return err;
309 *reply = encode_fattr (*reply, &st, version);
310 return 0;
311}
312
313static error_t
314op_create (struct cache_handle *c,
315 int *p,
316 int **reply,
317 int version)
318{
319 error_t err;
320 char *name;
321 retry_type do_retry;
322 char retry_name [1024];
323 mach_port_t newport;
324 struct cache_handle *newc;
325 struct stat st;
326 mode_t mode;
327 int statchanged = 0;
328 off_t size;
329
330 p = decode_name (p, &name);
331 mode = ntohl (*p);
332 p++;
333
334 err = dir_lookup (c->port, name, O_NOTRANS0x0080 | O_CREAT0x0010 | O_TRUNC0x00010000, mode,
335 &do_retry, retry_name, &newport);
336 if (!err
337 && (do_retry != FS_RETRY_NORMAL
338 || retry_name[0] != '\0'))
339 err = EACCES((0x10 << 26) | ((13) & 0x3fff));
340
341 if (err)
342 return err;
343
344 if (!err)
345 err = io_stat (newport, &st);
346 if (err)
347 goto errout;
348
349 /* NetBSD ignores most of the setattr fields given; that's good enough
350 for me too. */
351
352 p++, p++; /* Skip uid and gid. */
353
354 size = ntohl (*p);
355 p++;
356 if (size != -1 && size != st.st_size)
357 {
358 err = file_set_size (newport, size);
359 statchanged = 1;
360 }
361 if (err)
362 goto errout;
363
364 /* Ignore times. */
365
366 if (statchanged)
367 err = io_stat (newport, &st);
368
369 if (err)
370 {
371 errout:
372 dir_unlink (c->port, name);
373 free (name);
374 return err;
375 }
376 free (name);
377
378 newc = create_cached_handle (*(int *)c->handle, c, newport);
379 if (!newc)
380 return ESTALE((0x10 << 26) | ((70) & 0x3fff));
381
382 *reply = encode_fhandle (*reply, newc->handle);
383 *reply = encode_fattr (*reply, &st, version);
384 return 0;
385}
386
387static error_t
388op_remove (struct cache_handle *c,
389 int *p,
390 int **reply,
391 int version)
392{
393 error_t err;
394 char *name;
395
396 decode_name (p, &name);
397
398 err = dir_unlink (c->port, name);
Value stored to 'err' is never read
399 free (name);
400
401 return 0;
402}
403
404static error_t
405op_rename (struct cache_handle *fromc,
406 int *p,
407 int **reply,
408 int version)
409{
410 struct cache_handle *toc;
411 char *fromname, *toname;
412 error_t err = 0;
413
414 p = decode_name (p, &fromname);
415 p = lookup_cache_handle (p, &toc, fromc->ids);
416 decode_name (p, &toname);
417
418 if (!toc)
419 err = ESTALE((0x10 << 26) | ((70) & 0x3fff));
420 if (!err)
421 err = dir_rename (fromc->port, fromname, toc->port, toname, 0);
422 free (fromname);
423 free (toname);
424 return err;
425}
426
427static error_t
428op_link (struct cache_handle *filec,
429 int *p,
430 int **reply,
431 int version)
432{
433 struct cache_handle *dirc;
434 char *name;
435 error_t err = 0;
436
437 p = lookup_cache_handle (p, &dirc, filec->ids);
438 decode_name (p, &name);
439
440 if (!dirc)
441 err = ESTALE((0x10 << 26) | ((70) & 0x3fff));
442 if (!err)
443 err = dir_link (dirc->port, filec->port, name, 1);
444
445 free (name);
446 return err;
447}
448
449static error_t
450op_symlink (struct cache_handle *c,
451 int *p,
452 int **reply,
453 int version)
454{
455 char *name, *target;
456 error_t err;
457 mode_t mode;
458 file_t newport = MACH_PORT_NULL((mach_port_t) 0);
459 size_t len;
460 char *buf;
461
462 p = decode_name (p, &name);
463 p = decode_name (p, &target);
464 mode = ntohl (*p);
465 p++;
466 if (mode == -1)
467 mode = 0777;
468
469 len = strlen (target) + 1;
470 buf = alloca (sizeof (_HURD_SYMLINK) + len)__builtin_alloca (sizeof ("/hurd/" "symlink") + len);
471 memcpy (buf, _HURD_SYMLINK"/hurd/" "symlink", sizeof (_HURD_SYMLINK"/hurd/" "symlink"));
472 memcpy (buf + sizeof (_HURD_SYMLINK"/hurd/" "symlink"), target, len);
473
474 err = dir_mkfile (c->port, O_WRITE0x0002, mode, &newport);
475 if (!err)
476 err = file_set_translator (newport,
477 FS_TRANS_EXCL0x00000002|FS_TRANS_SET0x00000004,
478 FS_TRANS_EXCL0x00000002|FS_TRANS_SET0x00000004, 0,
479 buf, sizeof (_HURD_SYMLINK"/hurd/" "symlink") + len,
480 MACH_PORT_NULL((mach_port_t) 0), MACH_MSG_TYPE_COPY_SEND19);
481 if (!err)
482 err = dir_link (c->port, newport, name, 1);
483
484 free (name);
485 free (target);
486
487 if (newport != MACH_PORT_NULL((mach_port_t) 0))
488 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), newport);
489 return err;
490}
491
492static error_t
493op_mkdir (struct cache_handle *c,
494 int *p,
495 int **reply,
496 int version)
497{
498 char *name;
499 mode_t mode;
500 retry_type do_retry;
501 char retry_name [1024];
502 mach_port_t newport;
503 struct stat st;
504 struct cache_handle *newc;
505 error_t err;
506
507 p = decode_name (p, &name);
508 mode = ntohl (*p);
509 p++;
510
511 err = dir_mkdir (c->port, name, mode);
512
513 if (err)
514 {
515 free (name);
516 return err;
517 }
518
519 err = dir_lookup (c->port, name, O_NOTRANS0x0080, 0, &do_retry,
520 retry_name, &newport);
521 free (name);
522 if (!err
523 && (do_retry != FS_RETRY_NORMAL
524 || retry_name[0] != '\0'))
525 err = EACCES((0x10 << 26) | ((13) & 0x3fff));
526 if (err)
527 return err;
528
529 /* Ignore the rest of the sattr structure. */
530
531 if (!err)
532 err = io_stat (newport, &st);
533 if (err)
534 return err;
535
536 newc = create_cached_handle (*(int *)c->handle, c, newport);
537 if (!newc)
538 return ESTALE((0x10 << 26) | ((70) & 0x3fff));
539 *reply = encode_fhandle (*reply, newc->handle);
540 *reply = encode_fattr (*reply, &st, version);
541 return 0;
542}
543
544static error_t
545op_rmdir (struct cache_handle *c,
546 int *p,
547 int **reply,
548 int version)
549{
550 char *name;
551 error_t err;
552
553 decode_name (p, &name);
554
555 err = dir_rmdir (c->port, name);
556 free (name);
557 return err;
558}
559
560static error_t
561op_readdir (struct cache_handle *c,
562 int *p,
563 int **reply,
564 int version)
565{
566 int cookie;
567 unsigned count;
568 error_t err;
569 char *buf;
570 struct dirent *dp;
571 size_t bufsize;
572 int nentries;
573 int i;
574 int *replystart;
575 int *r;
576
577 cookie = ntohl (*p);
578 p++;
579 count = ntohl (*p);
580 p++;
581
582 buf = (char *) 0;
583 bufsize = 0;
584 err = dir_readdir (c->port, &buf, &bufsize, cookie, -1, count, &nentries);
585 if (err)
586 {
587 if (buf)
588 munmap (buf, bufsize);
589 return err;
590 }
591
592 r = *reply;
593
594 if (nentries == 0)
595 {
596 *(r++) = htonl (0); /* No entry. */
597 *(r++) = htonl (1); /* EOF. */
598 }
599 else
600 {
601 for (i = 0, dp = (struct dirent *) buf, replystart = *reply;
602 ((char *)dp < buf + bufsize
603 && i < nentries
604 && (char *)reply < (char *)replystart + count);
605 i++, dp = (struct dirent *) ((char *)dp + dp->d_reclen))
606 {
607 *(r++) = htonl (1); /* Entry present. */
608 *(r++) = htonl (dp->d_ino);
609 r = encode_string (r, dp->d_name);
610 *(r++) = htonl (i + cookie + 1); /* Next entry. */
611 }
612 *(r++) = htonl (0); /* No more entries. */
613 *(r++) = htonl (0); /* Not EOF. */
614 }
615
616 *reply = r;
617
618 if (buf)
619 munmap (buf, bufsize);
620
621 return 0;
622}
623
624static size_t
625count_readdir_buffersize (int *p, int version)
626{
627 p++; /* Skip COOKIE. */
628 return ntohl (*p); /* Return COUNT. */
629}
630
631static error_t
632op_statfs (struct cache_handle *c,
633 int *p,
634 int **reply,
635 int version)
636{
637 struct statfs st;
638 error_t err;
639
640 err = file_statfs (c->port, &st);
641 if (!err)
642 *reply = encode_statfs (*reply, &st);
643 return err;
644}
645
646static error_t
647op_mnt (struct cache_handle *c,
648 int *p,
649 int **reply,
650 int version)
651{
652 file_t root;
653 struct cache_handle *newc;
654 char *name;
655
656 decode_name (p, &name);
657
658 root = file_name_lookup (name, 0, 0);
659 if (!root)
660 {
661 free (name);
662 return errno(*__errno_location ());
663 }
664
665 newc = create_cached_handle (enter_filesystem (name, root), c, root);
666 free (name);
667 if (!newc)
668 return ESTALE((0x10 << 26) | ((70) & 0x3fff));
669 *reply = encode_fhandle (*reply, newc->handle);
670 return 0;
671}
672
673static error_t
674op_getport (struct cache_handle *c,
675 int *p,
676 int **reply,
677 int version)
678{
679 int prog, vers, prot;
680
681 prog = ntohl (*p);
682 p++;
683 vers = ntohl (*p);
684 p++;
685 prot = ntohl (*p);
686 p++;
687
688 if (prot != IPPROTO_UDPIPPROTO_UDP)
689 *(*reply)++ = htonl (0);
690 else if ((prog == MOUNTPROG100005 && vers == MOUNTVERS1)
691 || (prog == NFS_PROGRAM((u_long)100003) && vers == NFS_VERSION((u_long)2)))
692 *(*reply)++ = htonl (NFS_PORT2049);
693 else if (prog == PMAPPROG((u_long)100000) && vers == PMAPVERS((u_long)2))
694 *(*reply)++ = htonl (PMAPPORT((u_short)111));
695 else
696 *(*reply)++ = 0;
697
698 return 0;
699}
700
701
702struct proctable nfs2table =
703{
704 NFS2PROC_NULL0, /* First proc. */
705 NFS2PROC_STATFS17, /* Last proc. */
706 {
707 { op_null, 0, 0, 0},
708 { op_getattr, 0, 1, 1},
709 { op_setattr, 0, 1, 1},
710 { 0, 0, 0, 0 }, /* Deprecated NFSPROC_ROOT. */
711 { op_lookup, 0, 1, 1},
712 { op_readlink, 0, 1, 1},
713 { op_read, count_read_buffersize, 1, 1},
714 { 0, 0, 0, 0 }, /* Nonexistent NFSPROC_WRITECACHE. */
715 { op_write, 0, 1, 1},
716 { op_create, 0, 1, 1},
717 { op_remove, 0, 1, 1},
718 { op_rename, 0, 1, 1},
719 { op_link, 0, 1, 1},
720 { op_symlink, 0, 1, 1},
721 { op_mkdir, 0, 1, 1},
722 { op_rmdir, 0, 1, 1},
723 { op_readdir, count_readdir_buffersize, 1, 1},
724 { op_statfs, 0, 1, 1},
725 }
726};
727
728
729struct proctable mounttable =
730{
731 MOUNTPROC_NULL0, /* First proc. */
732 MOUNTPROC_EXPORT5, /* Last proc. */
733 {
734 { op_null, 0, 0, 0},
735 { op_mnt, 0, 0, 1},
736 { 0, 0, 0, 0}, /* MOUNTPROC_DUMP */
737 { op_null, 0, 0, 0}, /* MOUNTPROC_UMNT */
738 { op_null, 0, 0, 0}, /* MOUNTPROC_UMNTALL */
739 { 0, 0, 0, 0}, /* MOUNTPROC_EXPORT */
740 }
741};
742
743struct proctable pmaptable =
744{
745 PMAPPROC_NULL((u_long)0), /* First proc. */
746 PMAPPROC_CALLIT((u_long)5), /* Last proc. */
747 {
748 { op_null, 0, 0, 0},
749 { 0, 0, 0, 0}, /* PMAPPROC_SET */
750 { 0, 0, 0, 0}, /* PMAPPROC_UNSET */
751 { op_getport, 0, 0, 0},
752 { 0, 0, 0, 0}, /* PMAPPROC_DUMP */
753 { 0, 0, 0, 0}, /* PMAPPROC_CALLIT */
754 }
755};