snoop_nfs3.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1991, 1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "%Z%%M% %I% %E% SMI" /* SunOS */
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/tiuser.h>
#include <setjmp.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <rpc/rpc_msg.h>
#include "snoop.h"
#include "snoop_nfs.h"
#include <sys/stat.h>
#include <sys/param.h>
#include <rpcsvc/nfs_prot.h>
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
extern jmp_buf xdr_err;
static void nfscall3(int);
static void nfsreply3(int);
static char *perms(int);
static char *filetype(int);
static char *sum_access(void);
static char *sum_readdirres(void);
static char *sum_readdirplusres(void);
static char *sum_createhow(void);
static char *sum_stablehow(void);
static void detail_sattr3(void);
static void detail_diropargs3(void);
static void detail_readdirres(void);
static void detail_readdirplusres(void);
static void detail_fattr3(void);
static void detail_access(void);
static void detail_mode(int);
static void detail_wcc_attr(void);
static void detail_pre_op_attr(char *);
static void detail_wcc_data(char *);
static void skip_postop(void);
static void skip_wcc_data(void);
static void skip_sattr3(void);
#define DONT_CHANGE 0
#define SET_TO_SERVER_TIME 1
#define SET_TO_CLIENT_TIME 2
#define UNCHECKED 0
#define GUARDED 1
#define EXCLUSIVE 2
#define ACCESS3_READ 0x0001
#define ACCESS3_LOOKUP 0x0002
#define ACCESS3_MODIFY 0x0004
#define ACCESS3_EXTEND 0x0008
#define ACCESS3_DELETE 0x0010
#define ACCESS3_EXECUTE 0x0020
#define UNSTABLE 0
#define DATA_SYNC 1
#define FILE_SYNC 2
#define NF3REG 1 /* regular file */
#define NF3DIR 2 /* directory */
#define NF3BLK 3 /* block special */
#define NF3CHR 4 /* character special */
#define NF3LNK 5 /* symbolic link */
#define NF3SOCK 6 /* unix domain socket */
#define NF3FIFO 7 /* named pipe */
#define NFS3_FHSIZE 64
static char *procnames_short[] = {
"NULL3", /* 0 */
"GETATTR3", /* 1 */
"SETATTR3", /* 2 */
"LOOKUP3", /* 3 */
"ACCESS3", /* 4 */
"READLINK3", /* 5 */
"READ3", /* 6 */
"WRITE3", /* 7 */
"CREATE3", /* 8 */
"MKDIR3", /* 9 */
"SYMLINK3", /* 10 */
"MKNOD3", /* 11 */
"REMOVE3", /* 12 */
"RMDIR3", /* 13 */
"RENAME3", /* 14 */
"LINK3", /* 15 */
"READDIR3", /* 16 */
"READDIRPLUS3", /* 17 */
"FSSTAT3", /* 18 */
"FSINFO3", /* 19 */
"PATHCONF3", /* 20 */
"COMMIT3", /* 21 */
};
static char *procnames_long[] = {
"Null procedure", /* 0 */
"Get file attributes", /* 1 */
"Set file attributes", /* 2 */
"Look up file name", /* 3 */
"Check access permission", /* 4 */
"Read from symbolic link", /* 5 */
"Read from file", /* 6 */
"Write to file", /* 7 */
"Create file", /* 8 */
"Make directory", /* 9 */
"Make symbolic link", /* 10 */
"Make special file", /* 11 */
"Remove file", /* 12 */
"Remove directory", /* 13 */
"Rename", /* 14 */
"Link", /* 15 */
"Read from directory", /* 16 */
"Read from directory - plus", /* 17 */
"Get filesystem statistics", /* 18 */
"Get filesystem information", /* 19 */
"Get POSIX information", /* 20 */
"Commit to stable storage", /* 21 */
};
#define MAXPROC 21
void
interpret_nfs3(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
char *line;
char buff[NFS_MAXPATHLEN + 1]; /* protocol allows longer */
u_longlong_t off;
int sz, how;
char *fh, *name;
if (proc < 0 || proc > MAXPROC)
return;
if (flags & F_SUM) {
line = get_sum_line();
if (type == CALL) {
(void) sprintf(line, "NFS C %s",
procnames_short[proc]);
line += strlen(line);
switch (proc) {
case NFSPROC3_GETATTR:
case NFSPROC3_READLINK:
case NFSPROC3_FSSTAT:
case NFSPROC3_FSINFO:
case NFSPROC3_PATHCONF:
(void) sprintf(line, sum_nfsfh3());
break;
case NFSPROC3_SETATTR:
(void) sprintf(line, sum_nfsfh3());
break;
case NFSPROC3_READDIR:
fh = sum_nfsfh3();
off = getxdr_u_longlong();
(void) getxdr_u_longlong();
sz = getxdr_u_long();
(void) sprintf(line, "%s Cookie=%llu for %lu",
fh, off, sz);
break;
case NFSPROC3_READDIRPLUS:
fh = sum_nfsfh3();
off = getxdr_u_longlong();
(void) getxdr_u_longlong();
sz = getxdr_u_long();
(void) sprintf(line,
"%s Cookie=%llu for %lu/%lu",
fh, off, sz, getxdr_u_long());
break;
case NFSPROC3_ACCESS:
fh = sum_nfsfh3();
(void) sprintf(line, "%s (%s)",
fh, sum_access());
break;
case NFSPROC3_LOOKUP:
case NFSPROC3_REMOVE:
case NFSPROC3_RMDIR:
case NFSPROC3_MKDIR:
fh = sum_nfsfh3();
(void) sprintf(line, "%s %s",
fh, getxdr_string(buff,
NFS_MAXPATHLEN));
break;
case NFSPROC3_CREATE:
fh = sum_nfsfh3();
name = getxdr_string(buff, NFS_MAXPATHLEN);
(void) sprintf(line, "%s (%s) %s",
fh, sum_createhow(), name);
break;
case NFSPROC3_MKNOD:
fh = sum_nfsfh3();
name = getxdr_string(buff, NFS_MAXPATHLEN);
how = getxdr_long();
(void) sprintf(line, "%s (%s) %s",
fh, filetype(how), name);
break;
case NFSPROC3_READ:
fh = sum_nfsfh3();
off = getxdr_u_longlong();
sz = getxdr_u_long();
(void) sprintf(line, "%s at %llu for %lu",
fh, off, sz);
break;
case NFSPROC3_WRITE:
fh = sum_nfsfh3();
off = getxdr_u_longlong();
sz = getxdr_u_long();
(void) sprintf(line, "%s at %llu for %lu (%s)",
fh, off, sz, sum_stablehow());
break;
case NFSPROC3_SYMLINK:
fh = sum_nfsfh3();
(void) sprintf(line, "%s %s",
fh, getxdr_string(buff,
NFS_MAXPATHLEN));
skip_sattr3();
line += strlen(line);
(void) sprintf(line, " to %s",
getxdr_string(buff, NFS_MAXPATHLEN));
break;
case NFSPROC3_RENAME:
fh = sum_nfsfh3();
(void) sprintf(line, "%s %s",
fh, getxdr_string(buff,
NFS_MAXPATHLEN));
line += strlen(line);
fh = sum_nfsfh3();
(void) sprintf(line, " to%s %s",
fh, getxdr_string(buff,
NFS_MAXPATHLEN));
break;
case NFSPROC3_LINK:
fh = sum_nfsfh3();
(void) sprintf(line, "%s", fh);
line += strlen(line);
fh = sum_nfsfh3();
(void) sprintf(line, " to%s %s",
fh, getxdr_string(buff,
NFS_MAXPATHLEN));
break;
case NFSPROC3_COMMIT:
fh = sum_nfsfh3();
off = getxdr_u_longlong();
sz = getxdr_u_long();
(void) sprintf(line, "%s at %llu for %lu",
fh, off, sz);
break;
default:
break;
}
check_retransmit(line, xid);
} else {
(void) sprintf(line, "NFS R %s ",
procnames_short[proc]);
line += strlen(line);
switch (proc) {
case NFSPROC3_LOOKUP:
if (sum_nfsstat3(line) == NFS3_OK)
(void) strcat(line, sum_nfsfh3());
break;
case NFSPROC3_CREATE:
case NFSPROC3_MKDIR:
case NFSPROC3_SYMLINK:
case NFSPROC3_MKNOD:
if (sum_nfsstat3(line) == NFS3_OK) {
if (getxdr_bool())
(void) strcat(line,
sum_nfsfh3());
}
break;
case NFSPROC3_READLINK:
if (sum_nfsstat3(line) == NFS3_OK) {
line += strlen(line);
skip_postop();
(void) sprintf(line, " (Path=%s)",
getxdr_string(buff,
NFS_MAXPATHLEN));
}
break;
case NFSPROC3_GETATTR:
case NFSPROC3_SETATTR:
case NFSPROC3_REMOVE:
case NFSPROC3_RMDIR:
case NFSPROC3_RENAME:
case NFSPROC3_LINK:
case NFSPROC3_FSSTAT:
case NFSPROC3_FSINFO:
case NFSPROC3_PATHCONF:
(void) sum_nfsstat3(line);
break;
case NFSPROC3_ACCESS:
if (sum_nfsstat3(line) == NFS3_OK) {
line += strlen(line);
skip_postop();
(void) sprintf(line, " (%s)",
sum_access());
}
break;
case NFSPROC3_WRITE:
if (sum_nfsstat3(line) == NFS3_OK) {
line += strlen(line);
skip_wcc_data();
sz = getxdr_u_long();
(void) sprintf(line, " %d (%s)",
sz, sum_stablehow());
}
break;
case NFSPROC3_READDIR:
if (sum_nfsstat3(line) == NFS3_OK)
(void) strcat(line, sum_readdirres());
break;
case NFSPROC3_READ:
if (sum_nfsstat3(line) == NFS3_OK) {
line += strlen(line);
skip_postop();
(void) sprintf(line, " (%lu bytes)",
getxdr_u_long());
if (getxdr_bool())
(void) strcat(line, " EOF");
}
break;
case NFSPROC3_READDIRPLUS:
if (sum_nfsstat3(line) == NFS3_OK)
(void) strcat(line,
sum_readdirplusres());
break;
case NFSPROC3_COMMIT:
(void) sum_nfsstat3(line);
break;
default:
break;
}
}
}
if (flags & F_DTAIL) {
show_header("NFS: ", "Sun NFS", len);
show_space();
(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
proc, procnames_long[proc]);
if (type == CALL)
nfscall3(proc);
else
nfsreply3(proc);
show_trailer();
}
}
/*
* Print out version 3 NFS call packets
*/
static void
nfscall3(proc)
int proc;
{
int h;
switch (proc) {
case NFSPROC3_GETATTR:
case NFSPROC3_READLINK:
case NFSPROC3_FSINFO:
case NFSPROC3_FSSTAT:
case NFSPROC3_PATHCONF:
detail_nfsfh3();
break;
case NFSPROC3_SETATTR:
detail_nfsfh3();
detail_sattr3();
if (getxdr_bool())
(void) showxdr_date_ns("Guard = %s");
break;
case NFSPROC3_LOOKUP:
case NFSPROC3_REMOVE:
case NFSPROC3_RMDIR:
detail_diropargs3();
break;
case NFSPROC3_ACCESS:
detail_nfsfh3();
detail_access();
break;
case NFSPROC3_MKDIR:
detail_diropargs3();
detail_sattr3();
break;
case NFSPROC3_CREATE:
detail_diropargs3();
h = getxdr_u_long();
if (h == EXCLUSIVE)
showxdr_hex(8, "Guard = %s");
else {
(void) sprintf(get_line(0, 0), "Method = %s",
h == UNCHECKED ? "Unchecked" : "Guarded");
detail_sattr3();
}
break;
case NFSPROC3_MKNOD:
detail_diropargs3();
h = getxdr_u_long();
(void) sprintf(get_line(0, 0), "File type = %s",
filetype(h));
switch (h) {
case NF3CHR:
case NF3BLK:
detail_sattr3();
showxdr_u_long("Major = %lu");
showxdr_u_long("Minor = %lu");
break;
case NF3SOCK:
case NF3FIFO:
detail_sattr3();
break;
}
break;
case NFSPROC3_WRITE:
detail_nfsfh3();
(void) showxdr_u_longlong("Offset = %llu");
(void) showxdr_u_long("Size = %lu");
(void) sprintf(get_line(0, 0), "Stable = %s",
sum_stablehow());
break;
case NFSPROC3_RENAME:
detail_diropargs3();
detail_diropargs3();
break;
case NFSPROC3_LINK:
detail_nfsfh3();
detail_diropargs3();
break;
case NFSPROC3_SYMLINK:
detail_diropargs3();
detail_sattr3();
(void) showxdr_string(MAXPATHLEN, "Path = %s");
break;
case NFSPROC3_READDIR:
detail_nfsfh3();
(void) showxdr_u_longlong("Cookie = %llu");
(void) showxdr_hex(8, "Verifier = %s");
(void) showxdr_u_long("Count = %lu");
break;
case NFSPROC3_READDIRPLUS:
detail_nfsfh3();
(void) showxdr_u_longlong("Cookie = %llu");
(void) showxdr_hex(8, "Verifier = %s");
(void) showxdr_u_long("Dircount = %lu");
(void) showxdr_u_long("Maxcount = %lu");
break;
case NFSPROC3_READ:
case NFSPROC3_COMMIT:
detail_nfsfh3();
(void) showxdr_u_longlong("Offset = %llu");
(void) showxdr_long("Count = %lu");
break;
default:
break;
}
}
/*
* Print out version 3 NFS reply packets
*/
static void
nfsreply3(proc)
int proc;
{
int bits;
switch (proc) {
case NFSPROC3_GETATTR:
if (detail_nfsstat3() == NFS3_OK) {
detail_fattr3();
}
break;
case NFSPROC3_SETATTR:
(void) detail_nfsstat3();
detail_wcc_data("");
break;
case NFSPROC3_WRITE:
if (detail_nfsstat3() == NFS3_OK) {
detail_wcc_data("");
(void) showxdr_u_long("Count = %lu bytes written");
(void) sprintf(get_line(0, 0), "Stable = %s",
sum_stablehow());
(void) showxdr_hex(8, "Verifier = %s");
} else
detail_wcc_data("");
break;
case NFSPROC3_LOOKUP:
if (detail_nfsstat3() == NFS3_OK) {
detail_nfsfh3();
detail_post_op_attr("(object)");
}
detail_post_op_attr("(directory)");
break;
case NFSPROC3_CREATE:
case NFSPROC3_MKDIR:
case NFSPROC3_SYMLINK:
case NFSPROC3_MKNOD:
if (detail_nfsstat3() == NFS3_OK) {
if (getxdr_bool())
detail_nfsfh3();
else
(void) sprintf(get_line(0, 0),
"(No file handle available)");
detail_post_op_attr("");
}
detail_wcc_data("");
break;
case NFSPROC3_READLINK:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) showxdr_string(MAXPATHLEN, "Path = %s");
} else
detail_post_op_attr("");
break;
case NFSPROC3_READ:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) showxdr_u_long("Count = %lu bytes read");
(void) showxdr_bool("End of file = %s");
} else
detail_post_op_attr("");
break;
case NFSPROC3_ACCESS:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) sprintf(get_line(0, 0), "Access = %s",
sum_access());
} else
detail_post_op_attr("");
break;
case NFSPROC3_REMOVE:
case NFSPROC3_RMDIR:
(void) detail_nfsstat3();
detail_wcc_data("");
break;
case NFSPROC3_RENAME:
(void) detail_nfsstat3();
detail_wcc_data("(from directory)");
detail_wcc_data("(to directory)");
break;
case NFSPROC3_LINK:
(void) detail_nfsstat3();
detail_post_op_attr("");
detail_wcc_data("");
break;
case NFSPROC3_READDIR:
if (detail_nfsstat3() == NFS3_OK) {
detail_readdirres();
} else
detail_post_op_attr("");
break;
case NFSPROC3_READDIRPLUS:
if (detail_nfsstat3() == NFS3_OK) {
detail_readdirplusres();
} else
detail_post_op_attr("");
break;
case NFSPROC3_FSSTAT:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) showxdr_u_longlong(
"Total space = %llu bytes");
(void) showxdr_u_longlong(
"Available space = %llu bytes");
(void) showxdr_u_longlong(
"Available space - this user = %llu bytes");
(void) showxdr_u_longlong(
"Total file slots = %llu");
(void) showxdr_u_longlong(
"Available file slots = %llu");
(void) showxdr_u_longlong(
"Available file slots - this user = %llu");
(void) showxdr_u_long("Invariant time = %lu sec");
} else
detail_post_op_attr("");
break;
case NFSPROC3_FSINFO:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) show_line("Read transfer sizes:");
(void) showxdr_u_long(" Maximum = %lu bytes");
(void) showxdr_u_long(" Preferred = %lu bytes");
(void) showxdr_u_long(
" Suggested multiple = %lu bytes");
(void) show_line("Write transfer sizes:");
(void) showxdr_u_long(" Maximum = %lu bytes");
(void) showxdr_u_long(" Preferred = %lu bytes");
(void) showxdr_u_long(
" Suggested multiple = %lu bytes");
(void) show_line("Directory read size:");
(void) showxdr_u_long(" Preferred = %lu bytes");
(void) show_line("File system limits:");
(void) showxdr_u_longlong(
" Max file size = %llu bytes");
(void) showxdr_date_ns(
" Server minimum time discrimination = %s sec");
bits = showxdr_u_long("Properties = 0x%02x");
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, FSF3_LINK,
"Hard links supported",
"(hard links not supported)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, FSF3_SYMLINK,
"Symbolic links supported",
"(symbolic links not supported)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, FSF3_HOMOGENEOUS,
"Pathconf cannot vary per file",
"(pathconf can vary per file)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, FSF3_CANSETTIME,
"Server can always set file times",
"(server cannot always set file times)"));
} else
detail_post_op_attr("");
break;
case NFSPROC3_PATHCONF:
if (detail_nfsstat3() == NFS3_OK) {
detail_post_op_attr("");
(void) showxdr_u_long("Link max = %lu");
(void) showxdr_u_long("Name max = %lu");
(void) showxdr_bool("No trunc = %s");
(void) showxdr_bool("Chown restricted = %s");
(void) showxdr_bool("Case insensitive = %s");
(void) showxdr_bool("Case preserving = %s");
} else
detail_post_op_attr("");
break;
case NFSPROC3_COMMIT:
if (detail_nfsstat3() == NFS3_OK) {
detail_wcc_data("");
(void) showxdr_hex(8, "Verifier = %s");
} else
detail_wcc_data("");
break;
default:
break;
}
}
static void
detail_diropargs3()
{
detail_nfsfh3();
(void) showxdr_string(MAXPATHLEN, "File name = %s");
}
int
sum_nfsstat3(line)
char *line;
{
ulong_t status;
char *p;
status = getxdr_long();
switch (status) {
case NFS3_OK: p = "OK"; break;
case NFS3ERR_PERM: p = "Not owner"; break;
case NFS3ERR_NOENT: p = "No such file or directory"; break;
case NFS3ERR_IO: p = "I/O error"; break;
case NFS3ERR_NXIO: p = "No such device or address"; break;
case NFS3ERR_ACCES: p = "Permission denied"; break;
case NFS3ERR_EXIST: p = "File exists"; break;
case NFS3ERR_XDEV: p = "Attempted cross-device link"; break;
case NFS3ERR_NODEV: p = "No such device"; break;
case NFS3ERR_NOTDIR: p = "Not a directory"; break;
case NFS3ERR_ISDIR: p = "Is a directory"; break;
case NFS3ERR_INVAL: p = "Invalid argument"; break;
case NFS3ERR_FBIG: p = "File too large"; break;
case NFS3ERR_NOSPC: p = "No space left on device"; break;
case NFS3ERR_ROFS: p = "Read-only file system"; break;
case NFS3ERR_MLINK: p = "Too many links"; break;
case NFS3ERR_NAMETOOLONG:p = "File name too long"; break;
case NFS3ERR_NOTEMPTY: p = "Directory not empty"; break;
case NFS3ERR_DQUOT: p = "Disc quota exceeded"; break;
case NFS3ERR_STALE: p = "Stale NFS file handle"; break;
case NFS3ERR_REMOTE: p = "Too many levels of remote in path"; break;
case NFS3ERR_BADHANDLE: p = "Illegal NFS file handle"; break;
case NFS3ERR_NOT_SYNC: p = "Update synch mismatch"; break;
case NFS3ERR_BAD_COOKIE:p = "Readdir cookie is stale"; break;
case NFS3ERR_NOTSUPP: p = "Operation not supported"; break;
case NFS3ERR_TOOSMALL: p = "Buffer/request too small"; break;
case NFS3ERR_SERVERFAULT:p = "Server fault"; break;
case NFS3ERR_BADTYPE: p = "Bad type"; break;
case NFS3ERR_JUKEBOX: p = "File is temporarily unavailable"; break;
default: p = "(unknown error)"; break;
}
(void) strcpy(line, p);
return (status);
}
int
detail_nfsstat3()
{
ulong_t status;
char buff[64];
int pos;
pos = getxdr_pos();
status = sum_nfsstat3(buff);
(void) sprintf(get_line(pos, getxdr_pos()), "Status = %d (%s)",
status, buff);
return ((int)status);
}
static void
skip_postop()
{
if (getxdr_bool())
xdr_skip(21 * 4); /* XDR size of fattr3 */
}
static void
skip_wcc_data()
{
if (getxdr_bool() > 0)
xdr_skip(3 * 8);
skip_postop();
}
static void
skip_sattr3()
{
if (getxdr_bool() > 0)
xdr_skip(4); /* mode */
if (getxdr_bool() > 0)
xdr_skip(4); /* uid */
if (getxdr_bool() > 0)
xdr_skip(4); /* gid */
if (getxdr_bool() > 0)
xdr_skip(8); /* size */
if (getxdr_bool() > 0)
xdr_skip(8); /* atime */
if (getxdr_bool() > 0)
xdr_skip(8); /* mtime */
}
char *
sum_nfsfh3()
{
int len;
int fh;
static char buff[16];
len = getxdr_long();
fh = sum_filehandle(len);
(void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
return (buff);
}
void
detail_nfsfh3()
{
int pos;
int i, l, len;
int fh;
len = getxdr_long();
pos = getxdr_pos();
fh = sum_filehandle(len);
setxdr_pos(pos);
(void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
i = 0;
while (i < len) {
l = MIN(len - i, 32);
(void) showxdr_hex(l, " %s");
i += l;
}
}
static char *
sum_access()
{
int bits;
static char buff[64];
bits = getxdr_u_long();
buff[0] = '\0';
if (bits & ACCESS3_READ)
(void) strcat(buff, "read,");
if (bits & ACCESS3_LOOKUP)
(void) strcat(buff, "lookup,");
if (bits & ACCESS3_MODIFY)
(void) strcat(buff, "modify,");
if (bits & ACCESS3_EXTEND)
(void) strcat(buff, "extend,");
if (bits & ACCESS3_DELETE)
(void) strcat(buff, "delete,");
if (bits & ACCESS3_EXECUTE)
(void) strcat(buff, "execute,");
if (buff[0] != '\0')
buff[strlen(buff) - 1] = '\0';
return (buff);
}
static void
detail_access()
{
uint_t bits;
bits = showxdr_u_long("Access bits = 0x%08x");
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_READ, "Read", "(no read)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_LOOKUP, "Lookup", "(no lookup)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_MODIFY, "Modify", "(no modify)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_EXTEND, "Extend", "(no extend)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_DELETE, "Delete", "(no delete)"));
(void) sprintf(get_line(0, 0), " %s",
getflag(bits, ACCESS3_EXECUTE, "Execute", "(no execute)"));
}
static void
detail_mode(mode)
int mode;
{
(void) sprintf(get_line(0, 0), " Mode = 0%o", mode);
(void) sprintf(get_line(0, 0),
" Setuid = %d, Setgid = %d, Sticky = %d",
(mode & S_ISUID) != 0,
(mode & S_ISGID) != 0,
(mode & S_ISVTX) != 0);
(void) sprintf(get_line(0, 0), " Owner's permissions = %s",
perms(mode >> 6 & 0x7));
(void) sprintf(get_line(0, 0), " Group's permissions = %s",
perms(mode >> 3 & 0x7));
(void) sprintf(get_line(0, 0), " Other's permissions = %s",
perms(mode & 0x7));
}
static void
detail_fattr3()
{
uint_t fltype, mode, nlinks, uid, gid;
uint_t major, minor;
u_longlong_t size, used, fsid, fileid;
fltype = getxdr_u_long();
mode = getxdr_u_long();
nlinks = getxdr_u_long();
uid = getxdr_u_long();
gid = getxdr_u_long();
size = getxdr_u_longlong();
used = getxdr_u_longlong();
major = getxdr_u_long();
minor = getxdr_u_long();
fsid = getxdr_u_longlong();
fileid = getxdr_u_longlong();
(void) sprintf(get_line(0, 0),
" File type = %d (%s)",
fltype, filetype(fltype));
detail_mode(mode);
(void) sprintf(get_line(0, 0),
" Link count = %u, User ID = %u, Group ID = %u",
nlinks, uid, gid);
(void) sprintf(get_line(0, 0),
" File size = %llu, Used = %llu",
size, used);
(void) sprintf(get_line(0, 0),
" Special: Major = %u, Minor = %u",
major, minor);
(void) sprintf(get_line(0, 0),
" File system id = %llu, File id = %llu",
fsid, fileid);
(void) showxdr_date_ns(" Last access time = %s");
(void) showxdr_date_ns(" Modification time = %s");
(void) showxdr_date_ns(" Attribute change time = %s");
(void) show_line("");
}
static void
detail_sattr3()
{
int t;
if (getxdr_bool())
detail_mode(getxdr_u_long());
else
(void) sprintf(get_line(0, 0), "Mode = (not set)");
if (getxdr_bool())
(void) showxdr_long("User ID = %d");
else
(void) sprintf(get_line(0, 0), "User ID = (not set)");
if (getxdr_bool())
(void) showxdr_long("Group ID = %d");
else
(void) sprintf(get_line(0, 0), "Group ID = (not set)");
if (getxdr_bool())
(void) showxdr_u_longlong("Size = %llu");
else
(void) sprintf(get_line(0, 0), "Size = (not set)");
if ((t = getxdr_u_long()) == SET_TO_CLIENT_TIME)
(void) showxdr_date("Access time = %s (set to client time)");
else if (t == SET_TO_SERVER_TIME)
(void) sprintf(get_line(0, 0),
"Access time = (set to server time)");
else
(void) sprintf(get_line(0, 0), "Access time = (do not set)");
if ((t = getxdr_u_long()) == SET_TO_CLIENT_TIME) {
(void) showxdr_date(
"Modification time = %s (set to client time)");
} else if (t == SET_TO_SERVER_TIME)
(void) sprintf(get_line(0, 0),
"Modification time = (set to server time)");
else
(void) sprintf(get_line(0, 0),
"Modification time = (do not set)");
(void) show_line("");
}
static char *
filetype(n)
int n;
{
switch (n) {
case NF3REG:
return ("Regular File");
case NF3DIR:
return ("Directory");
case NF3BLK:
return ("Block special");
case NF3CHR:
return ("Character special");
case NF3LNK:
return ("Symbolic Link");
case NF3SOCK:
return ("Unix domain socket");
case NF3FIFO:
return ("Named pipe");
default:
return ("?");
}
/* NOTREACHED */
}
static char *
perms(n)
int n;
{
static char buff[4];
buff[0] = n & 4 ? 'r' : '-';
buff[1] = n & 2 ? 'w' : '-';
buff[2] = n & 1 ? 'x' : '-';
buff[3] = '\0';
return (buff);
}
static void
detail_wcc_attr()
{
(void) showxdr_u_longlong(" Size = %llu bytes");
(void) showxdr_date_ns(" Modification time = %s");
(void) showxdr_date_ns(" Attribute change time = %s");
(void) show_line("");
}
static void
detail_pre_op_attr(str)
char *str;
{
if (getxdr_bool()) {
(void) sprintf(get_line(0, 0),
"Pre-operation attributes: %s", str);
detail_wcc_attr();
} else
(void) sprintf(get_line(0, 0),
"Pre-operation attributes: %s (not available)", str);
}
void
detail_post_op_attr(str)
char *str;
{
if (getxdr_bool()) {
(void) sprintf(get_line(0, 0),
"Post-operation attributes: %s", str);
detail_fattr3();
} else
(void) sprintf(get_line(0, 0),
"Post-operation attributes: %s (not available)", str);
}
static void
detail_wcc_data(str)
char *str;
{
detail_pre_op_attr(str);
detail_post_op_attr(str);
}
static char *
sum_readdirres()
{
static char buff[NFS_MAXNAMLEN + 1]; /* protocol allows longer names */
static int entries;
entries = 0;
if (setjmp(xdr_err)) {
(void) sprintf(buff, " %d+ entries (incomplete)", entries);
return (buff);
}
skip_postop();
xdr_skip(8); /* cookieverf */
while (getxdr_bool()) {
entries++;
xdr_skip(8); /* fileid */
(void) getxdr_string(buff, NFS_MAXNAMLEN); /* name */
xdr_skip(8); /* cookie */
}
(void) sprintf(buff, " %d entries (%s)",
entries, getxdr_bool() ? "No more" : "More");
return (buff);
}
static char *
sum_readdirplusres()
{
static char buff[NFS_MAXNAMLEN + 1]; /* protocol allows longer */
static int entries;
int skip;
entries = 0;
if (setjmp(xdr_err)) {
(void) sprintf(buff, " %d+ entries (incomplete)", entries);
return (buff);
}
skip_postop();
xdr_skip(8); /* cookieverf */
while (getxdr_bool()) {
entries++;
xdr_skip(8); /* fileid */
(void) getxdr_string(buff, NFS_MAXNAMLEN); /* name */
xdr_skip(8); /* cookie */
skip_postop(); /* post-op */
if (getxdr_bool()) {
skip = getxdr_long();
xdr_skip(RNDUP(skip)); /* fhandle */
}
}
(void) sprintf(buff, " %d entries (%s)",
entries, getxdr_bool() ? "No more" : "More");
return (buff);
}
static void
detail_readdirres()
{
static int entries;
u_longlong_t fileid, cookie;
char *name;
char buff[NFS_MAXNAMLEN + 1]; /* protocol allows longer names */
entries = 0;
detail_post_op_attr("");
(void) showxdr_hex(8, "Cookie verifier = %s");
(void) show_line("");
(void) sprintf(get_line(0, 0), " File id Cookie Name");
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ entries. (Frame is incomplete)",
entries);
return;
}
while (getxdr_bool()) {
entries++;
fileid = getxdr_u_longlong();
name = (char *)getxdr_string(buff, NFS_MAXNAMLEN);
cookie = getxdr_u_longlong();
(void) sprintf(get_line(0, 0),
" %10llu %10llu %s",
fileid, cookie, name);
}
(void) sprintf(get_line(0, 0), " %d entries", entries);
(void) showxdr_bool("EOF = %s");
}
static void
detail_readdirplusres()
{
static int entries;
entries = 0;
detail_post_op_attr("");
(void) showxdr_hex(8, "Cookie verifier = %s");
(void) show_line("");
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ entries. (Frame is incomplete)",
entries);
return;
}
while (getxdr_bool()) {
entries++;
(void) sprintf(get_line(0, 0),
"------------------ entry #%d",
entries);
(void) showxdr_u_longlong("File ID = %llu");
(void) showxdr_string(NFS_MAXNAMLEN, "Name = %s");
(void) showxdr_u_longlong("Cookie = %llu");
detail_post_op_attr("");
if (getxdr_bool())
detail_nfsfh3();
else
(void) sprintf(get_line(0, 0),
"(No file handle available)");
}
(void) show_line("");
(void) sprintf(get_line(0, 0), " %d entries", entries);
(void) showxdr_bool("EOF = %s");
}
static char *
sum_createhow()
{
long how;
how = getxdr_long();
switch (how) {
case UNCHECKED:
return ("UNCHECKED");
case GUARDED:
return ("GUARDED");
case EXCLUSIVE:
return ("EXCLUSIVE");
default:
return ("?");
}
/* NOTREACHED */
}
static char *
sum_stablehow()
{
long stable;
stable = getxdr_long();
switch (stable) {
case UNSTABLE:
return ("ASYNC");
case DATA_SYNC:
return ("DSYNC");
case FILE_SYNC:
return ("FSYNC");
default:
return ("?");
}
/* NOTREACHED */
}