fs: rename AT_* to VATTR_*
[unleashed/lotheac.git] / usr / src / stand / lib / fs / nfs / nfsops.c
blob1bd4760e057309113749152188fcfcb701bad4f7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Simple nfs ops - open, close, read, and lseek.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <rpc/types.h>
31 #include <rpc/auth.h>
32 #include <sys/t_lock.h>
33 #include "clnt.h"
34 #include <sys/fcntl.h>
35 #include <sys/vfs.h>
36 #include <errno.h>
37 #include <sys/promif.h>
38 #include <rpc/xdr.h>
39 #include "nfs_inet.h"
40 #include <sys/stat.h>
41 #include <sys/bootvfs.h>
42 #include <sys/bootdebug.h>
43 #include <sys/salib.h>
44 #include <sys/sacache.h>
45 #include <rpc/rpc.h>
46 #include "brpc.h"
47 #include <rpcsvc/nfs_prot.h>
48 #include "socket_inet.h"
49 #include "mac.h"
50 #include <sys/mode.h>
52 ushort_t vttoif_tab[] = {
53 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
54 S_IFDOOR, 0, S_IFSOCK, 0
57 static int file_desc = 1;
58 static struct nfs_files {
59 struct nfs_file file;
60 int desc;
61 struct nfs_files *next;
62 } nfs_files[1] = {
63 {0, 0, 0},
66 #define dprintf if (boothowto & RB_DEBUG) printf
68 static int boot_nfs_open(char *filename, int flags);
69 static int boot_nfs_close(int fd);
70 static ssize_t boot_nfs_read(int fd, caddr_t buf, size_t size);
71 static off_t boot_nfs_lseek(int, off_t, int);
72 static int boot_nfs_fstat(int fd, struct bootstat *stp);
73 static void boot_nfs_closeall(int flag);
74 static int boot_nfs_getdents(int fd, struct dirent *dep, unsigned size);
76 struct boot_fs_ops boot_nfs_ops = {
77 "nfs",
78 boot_nfs_mountroot,
79 boot_nfs_unmountroot,
80 boot_nfs_open,
81 boot_nfs_close,
82 boot_nfs_read,
83 boot_nfs_lseek,
84 boot_nfs_fstat,
85 boot_nfs_closeall,
86 boot_nfs_getdents
90 * bootops.c calls a closeall() function to close all open files. Since
91 * we only permit one open file at a time (not counting the device), this
92 * is simple to implement.
95 /*ARGSUSED*/
96 static void
97 boot_nfs_closeall(int flag)
99 struct nfs_files *filep;
101 #ifdef NFS_OPS_DEBUG
102 if ((boothowto & DBFLAGS) == DBFLAGS)
103 printf("boot_nfs_closeall(%x)\n", flag);
104 #endif
106 if (nfs_files->file.version == 0 &&
107 nfs_files->desc == 0 &&
108 nfs_files->next == NULL)
109 return;
111 /* delete any dynamically allocated entries */
112 while ((filep = nfs_files->next) != NULL) {
113 nfs_files->next = filep->next;
114 bkmem_free((caddr_t)filep, sizeof (struct nfs_files));
117 /* clear the first, static file */
118 bzero((caddr_t)nfs_files, sizeof (struct nfs_files));
120 /* Close device */
121 release_cache(mac_get_dev());
123 mac_fini();
127 * Get a file pointer given a file descriptor. Return 0 on error
129 static struct nfs_files *
130 get_filep(int fd)
132 struct nfs_files *filep;
134 for (filep = nfs_files; filep; filep = filep->next) {
135 if (fd == filep->desc)
136 return (filep);
138 return (NULL);
142 * Unmount the root fs -- not supported for this fstype.
146 boot_nfs_unmountroot(void)
148 return (-1);
152 * open a file for reading. Note: writing is NOT supported.
155 static int
156 boot_nfs_open(char *path, int flags)
158 struct nfs_files *filep, *newfilep;
159 int got_filep;
161 #ifdef NFS_OPS_DEBUG
162 if ((boothowto & DBFLAGS) == DBFLAGS)
163 printf("boot_nfs_open(%s, %x)\n", path, flags);
164 #endif
166 /* file can only be opened readonly. */
167 if (flags & ~O_RDONLY) {
168 dprintf("boot_nfs_open: files can only be opened O_RDONLY.\n");
169 return (-1);
172 if (path == NULL || *path == '\0') {
173 dprintf("boot_nfs_open: NULL or EMPTY pathname argument.\n");
174 return (-1);
177 /* Try and find a vacant file pointer */
178 filep = nfs_files;
179 got_filep = FALSE;
180 do {
181 if (filep->desc == 0) {
182 filep->desc = file_desc++;
183 got_filep = TRUE;
184 break; /* We've got a file pointer */
186 /* Get next entry if not at end of list */
187 if (filep->next)
188 filep = filep->next;
189 } while (filep->next);
191 /* If a a vacant file pointer cannot be found, make one */
192 if (!got_filep) {
193 if ((newfilep = (struct nfs_files *)
194 bkmem_zalloc(sizeof (struct nfs_files))) == 0) {
195 dprintf("open: Cannot allocate file pointer\n");
196 return (-1);
198 filep->next = newfilep;
199 filep = newfilep;
200 filep->desc = file_desc++;
203 if (lookup(path, &filep->file, FALSE) != 0) {
204 #ifdef NFS_OPS_DEBUG
205 if ((boothowto & DBFLAGS) == DBFLAGS)
206 printf("boot_nfs_open(): Cannot open '%s'.\n", path);
207 #endif
208 /* zero file pointer */
209 bzero((caddr_t)filep, sizeof (struct nfs_file));
210 filep->desc = 0;
211 return (-1);
213 bzero(&filep->file.cookie, sizeof (filep->file.cookie));
215 #ifdef NFS_OPS_DEBUG
216 if ((boothowto & DBFLAGS) == DBFLAGS)
217 printf("boot_nfs_open(): '%s' successful, fd = 0x%x\n",
218 path, filep->desc);
219 #endif
220 return (filep->desc);
224 * close a previously opened file.
226 static int
227 boot_nfs_close(int fd)
229 struct nfs_files *filep;
231 #ifdef NFS_OPS_DEBUG
232 if ((boothowto & DBFLAGS) == DBFLAGS)
233 printf("boot_nfs_close(%d)\n", fd);
234 #endif
235 if ((filep = get_filep(fd)) == 0)
236 return (0);
239 * zero file pointer
241 bzero((caddr_t)&filep->file, sizeof (struct nfs_file));
244 * "close" the fd.
246 filep->desc = 0;
248 return (0);
252 * read from a file.
254 static ssize_t
255 boot_nfs_read(int fd, char *buf, size_t size)
257 struct nfs_files *filep;
258 int count = 0;
260 if (fd == 0) {
261 dprintf("boot_nfs_read: Bad file number.\n");
262 return (-1);
264 if (buf == NULL) {
265 dprintf("boot_nfs_read: Bad address.\n");
266 return (-1);
269 #ifdef NFS_OPS_DEBUG
270 if ((boothowto & DBFLAGS) == DBFLAGS)
271 printf("boot_nfs_read(%d, %x, 0x%x)\n", fd, buf, size);
272 #endif
274 /* initialize for read */
275 if ((filep = get_filep(fd)) == 0)
276 return (-1);
278 switch (filep->file.version) {
279 case NFS_VERSION:
280 count = nfsread(&filep->file, buf, size);
281 break;
282 case NFS_V3:
283 count = nfs3read(&filep->file, buf, size);
284 break;
285 case NFS_V4:
286 count = nfs4read(&filep->file, buf, size);
287 break;
288 default:
289 printf("boot_nfs_read: NFS Version %d not supported\n",
290 filep->file.version);
291 count = -1;
292 break;
295 #ifdef NFS_OPS_DEBUG
296 if ((boothowto & DBFLAGS) == DBFLAGS)
297 printf("boot_nfs_read(): 0x%x bytes.\n", count);
298 #endif
299 return (count);
303 * lseek - move read file pointer.
306 static off_t
307 boot_nfs_lseek(int fd, off_t offset, int whence)
309 struct nfs_files *filep;
311 #ifdef NFS_OPS_DEBUG
312 if ((boothowto & DBFLAGS) == DBFLAGS)
313 printf("boot_nfs_lseek(%d, 0x%x, %d)\n", fd, offset, whence);
314 #endif
316 if (fd == 0) {
317 dprintf("boot_nfs_lseek: Bad file number.\n");
318 return (-1);
321 if ((filep = get_filep(fd)) == 0)
322 return (-1);
324 switch (whence) {
326 case SEEK_SET:
328 * file ptr is set to offset from beginning of file
330 filep->file.offset = offset;
331 break;
332 case SEEK_CUR:
334 * file ptr is set to offset from current position
336 filep->file.offset += offset;
337 break;
338 case SEEK_END:
340 * file ptr is set to current size of file plus offset.
341 * But since we only support reading, this is illegal.
343 default:
345 * invalid offset origin
347 dprintf("boot_nfs_lseek: invalid whence value.\n");
348 return (-1);
351 #ifdef notyet
352 return (filep->file.offset);
353 #else
355 * BROKE - lseek should return the offset seeked to on a
356 * successful seek, not zero - This must be fixed in the
357 * kernel before It can be fixed here.
359 return (0);
360 #endif /* notyet */
364 * This version of fstat supports mode, size, inode #, and times only.
365 * It can be enhanced if more is required,
368 static int
369 boot_nfs_fstat(int fd, struct bootstat *stp)
371 struct vattr va;
372 struct nfs_files *filep;
373 int status;
375 #ifdef NFS_OPS_DEBUG
376 if ((boothowto & DBFLAGS) == DBFLAGS) {
377 printf("boot_nfs_fstat(%d, 0x%x)\n", fd, stp);
379 #endif
380 if (fd == 0) {
381 dprintf("boot_nfs_fstat(): Bad file number 0.\n");
382 return (-1);
385 if ((filep = get_filep(fd)) == 0)
386 return (-1);
388 bzero((char *)&va, sizeof (va));
389 va.va_mask = VATTR_TYPE | VATTR_SIZE | VATTR_MODE | VATTR_NODEID |
390 VATTR_ATIME | VATTR_CTIME | VATTR_MTIME;
392 switch (filep->file.version) {
393 case NFS_VERSION:
394 status = nfsgetattr(&filep->file, &va);
395 break;
396 case NFS_V3:
397 status = nfs3getattr(&filep->file, &va);
398 break;
399 case NFS_V4:
400 status = nfs4getattr(&filep->file, &va);
401 break;
402 default:
403 printf("boot_nfs_fstat: NFS Version %d not supported\n",
404 filep->file.version);
405 status = -1;
406 break;
409 if (status != 0)
410 return (-1);
412 if (va.va_size > (uoff_t)MAXOFF_T) {
413 dprintf("boot_nfs_fstat(): File too large.\n");
414 return (-1);
416 stp->st_size = (off_t)va.va_size;
417 stp->st_mode = VTTOIF(va.va_type) | va.va_mode;
418 stp->st_atim.tv_sec = va.va_atime.tv_sec;
419 stp->st_atim.tv_nsec = va.va_atime.tv_nsec;
420 stp->st_ctim.tv_sec = va.va_ctime.tv_sec;
421 stp->st_ctim.tv_nsec = va.va_ctime.tv_nsec;
422 stp->st_mtim.tv_sec = va.va_mtime.tv_sec;
423 stp->st_mtim.tv_nsec = va.va_mtime.tv_nsec;
424 stp->st_ino = (ino_t)va.va_nodeid;
426 #ifdef NFS_OPS_DEBUG
427 if ((boothowto & DBFLAGS) == DBFLAGS)
428 printf("boot_nfs_fstat(): done.\n");
429 #endif
430 return (0);
433 static int
434 boot_nfs_getdents(int fd, struct dirent *dep, unsigned size)
436 struct nfs_files *filep;
437 int status;
439 #ifdef NFS_OPS_DEBUG
440 if ((boothowto & DBFLAGS) == DBFLAGS) {
441 printf("boot_nfs_getdents(%d, 0x%x, 0x%x)\n", fd, dep, size);
443 #endif
445 if (fd == 0) {
446 dprintf("boot_nfs_getdents(): Bad file number 0.\n");
447 return (-1);
450 if ((filep = get_filep(fd)) == 0)
451 return (-1);
453 switch (filep->file.version) {
454 case NFS_VERSION:
455 status = nfsgetdents(&filep->file, dep, size);
456 break;
457 case NFS_V3:
458 status = nfs3getdents(&filep->file, dep, size);
459 break;
460 default:
461 printf("boot_nfs_getdents: NFS Version %d not supported\n",
462 filep->file.version);
463 status = -1;
466 #ifdef NFS_OPS_DEBUG
467 if ((boothowto & DBFLAGS) == DBFLAGS)
468 printf("boot_nfs_getdents(): done.\n");
469 #endif
470 return (status);