#include <assert.h>
#include <errno.h>
#include <nfs/nfs.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
#include <libintl.h>
#include <unistd.h>
#include <nfs/nfs.h>
#include <nfs/nfs_log.h>
#include "fhtab.h"
#include "nfslogd.h"
#define ROUNDUP32(val) (((val) + 3) & ~3)
#define IS_DOT_FILENAME(name) \
((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
#define PRINT_LINK_DATA(fp, func, dfh, name, str) \
(void) fprintf(fp, "%s: name '%s', dfh ", \
func, (((name) != NULL) ? name : "")); \
debug_opaque_print(fp, dfh, sizeof (*(dfh))); \
(void) fprintf(fp, "%s\n", str);
#define PRINT_FULL_DATA(fp, func, dfh, fh, name, str) \
(void) fprintf(fp, "%s: name '%s', dfh ", \
func, (((name) != NULL) ? name : "")); \
debug_opaque_print(fp, dfh, sizeof (*(dfh))); \
if ((fh) != NULL) { \
(void) fprintf(fp, ", fh "); \
debug_opaque_print(fp, fh, sizeof (*(fh))); \
} \
(void) fprintf(fp, "%s\n", str);
struct export_handle_cache {
fhandle_t fh;
char *name;
struct export_handle_cache *next;
};
static struct export_handle_cache *exp_handle_cache = NULL;
extern bool_t nfsl_prin_fh;
static int fh_add(char *, fhandle_t *, fhandle_t *, char *);
static char *get_export_path(fhandle_t *, char *);
static void sprint_fid(char *, uint_t, const fhandle_t *);
static void fh_print_all_keys(char *fhpath, fhandle_t *fh);
static int fh_compare(fhandle_t *fh1, fhandle_t *fh2);
static fhlist_ent *fh_lookup(char *fhpath, fhandle_t *fh, fhlist_ent *fhrecp,
int *errorp);
static int fh_remove_mc_link(char *fhpath, fhandle_t *dfh, char *name,
char **pathp);
static int fh_remove(char *fhpath, fhandle_t *dfh, char *name, char **pathp);
static int fh_rename(char *fhpath, fhandle_t *from_dfh, char *from_name,
char **from_pathp, fhandle_t *to_dfh, char *to_name);
static fhlist_ent *fh_lookup_link(char *fhpath, fhandle_t *dfh, fhandle_t *fh,
char *name, fhlist_ent *fhrecp, int *errorp);
static struct nfsl_fh_proc_disp *nfslog_find_fh_dispatch(
nfslog_request_record *);
static struct export_handle_cache *find_fh_in_export_cache(fhandle_t *fh);
static void add_fh_to_export_cache(fhandle_t *fh, char *path);
static char *update_export_point(char *fhpath, fhandle_t *fh, char *path);
static char *fh_print_absolute(char *fhpath, fhandle_t *fh, char *name);
static void nfslog_null_fhargs(caddr_t *nfsl_args, caddr_t *nfsl_res,
char *fhpath, char **pathp1, char **pathp2);
static void nfslog_LOOKUP_calc(fhandle_t *dfh, char *name, fhandle_t *fh,
char *fhpath, char **pathp1, char **pathp2, char *str);
static void nfslog_GETATTR2_fhargs(fhandle_t *,
nfsstat *, char *fhpath, char **, char **);
static void nfslog_SETATTR2_fhargs(nfslog_setattrargs *, nfsstat *,
char *, char **, char **);
static void nfslog_LOOKUP2_fhargs(nfslog_diropargs *, nfslog_diropres *,
char *, char **, char **);
static void nfslog_READLINK2_fhargs(fhandle_t *, nfslog_rdlnres *,
char *, char **, char **);
static void nfslog_READ2_fhargs(nfslog_nfsreadargs *, nfslog_rdresult *,
char *, char **, char **);
static void nfslog_WRITE2_fhargs(nfslog_writeargs *, nfslog_writeresult *,
char *, char **, char **);
static void nfslog_CREATE2_fhargs(nfslog_createargs *, nfslog_diropres*,
char *, char **, char **);
static void nfslog_REMOVE2_fhargs(nfslog_diropargs *, nfsstat *,
char *, char **, char **);
static void nfslog_RENAME2_fhargs(nfslog_rnmargs *, nfsstat *,
char *, char **, char **);
static void nfslog_LINK2_fhargs(nfslog_linkargs *, nfsstat *,
char *, char **, char **);
static void nfslog_SYMLINK2_fhargs(nfslog_symlinkargs *, nfsstat *,
char *, char **, char **);
static void nfslog_READDIR2_fhargs(nfslog_rddirargs *, nfslog_rddirres *,
char *, char **, char **);
static void nfslog_STATFS2_fhargs(fhandle_t *, nfsstat *,
char *, char **, char **);
static void nfslog_GETATTR3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_SETATTR3_fhargs(nfslog_SETATTR3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_LOOKUP3_fhargs(nfslog_diropargs3 *, nfslog_LOOKUP3res *,
char *, char **, char **);
static void nfslog_ACCESS3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_READLINK3_fhargs(nfs_fh3 *, nfslog_READLINK3res *,
char *, char **, char **);
static void nfslog_READ3_fhargs(nfslog_READ3args *, nfslog_READ3res *,
char *, char **, char **);
static void nfslog_WRITE3_fhargs(nfslog_WRITE3args *, nfslog_WRITE3res *,
char *, char **, char **);
static void nfslog_CREATE3_fhargs(nfslog_CREATE3args *, nfslog_CREATE3res *,
char *, char **, char **);
static void nfslog_MKDIR3_fhargs(nfslog_MKDIR3args *, nfslog_MKDIR3res *,
char *, char **, char **);
static void nfslog_SYMLINK3_fhargs(nfslog_SYMLINK3args *, nfslog_SYMLINK3res *,
char *, char **, char **);
static void nfslog_MKNOD3_fhargs(nfslog_MKNOD3args *, nfslog_MKNOD3res *,
char *, char **, char **);
static void nfslog_REMOVE3_fhargs(nfslog_REMOVE3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_RMDIR3_fhargs(nfslog_RMDIR3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_RENAME3_fhargs(nfslog_RENAME3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_LINK3_fhargs(nfslog_LINK3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_READDIR3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_READDIRPLUS3_fhargs(nfslog_READDIRPLUS3args *,
nfslog_READDIRPLUS3res *,
char *, char **, char **);
static void nfslog_FSSTAT3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_FSINFO3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_PATHCONF3_fhargs(nfs_fh3 *, nfsstat3 *,
char *, char **, char **);
static void nfslog_COMMIT3_fhargs(nfslog_COMMIT3args *, nfsstat3 *,
char *, char **, char **);
static void nfslog_SHARE_fhargs(nfslog_sharefsargs *, nfslog_sharefsres *,
char *, char **, char **);
static void nfslog_UNSHARE_fhargs(nfslog_sharefsargs *, nfslog_sharefsres *,
char *, char **, char **);
static void nfslog_GETFH_fhargs(nfslog_getfhargs *, nfsstat *,
char *, char **, char **);
static struct nfsl_fh_proc_disp nfsl_fh_proc_v2[] = {
{nfslog_null_fhargs, xdr_void, xdr_void, 0, 0},
{nfslog_GETATTR2_fhargs, xdr_fhandle, xdr_nfsstat,
sizeof (fhandle_t), sizeof (nfsstat)},
{nfslog_SETATTR2_fhargs, xdr_nfslog_setattrargs, xdr_nfsstat,
sizeof (nfslog_setattrargs), sizeof (nfsstat)},
{nfslog_null_fhargs, xdr_void, xdr_void, 0, 0},
{nfslog_LOOKUP2_fhargs, xdr_nfslog_diropargs, xdr_nfslog_diropres,
sizeof (nfslog_diropargs), sizeof (nfslog_diropres)},
{nfslog_READLINK2_fhargs, xdr_fhandle, xdr_nfslog_rdlnres,
sizeof (fhandle_t), sizeof (nfslog_rdlnres)},
{nfslog_READ2_fhargs, xdr_nfslog_nfsreadargs, xdr_nfslog_rdresult,
sizeof (nfslog_nfsreadargs), sizeof (nfslog_rdresult)},
{nfslog_null_fhargs, xdr_void, xdr_void, 0, 0},
{nfslog_WRITE2_fhargs, xdr_nfslog_writeargs, xdr_nfslog_writeresult,
sizeof (nfslog_writeargs), sizeof (nfslog_writeresult)},
{nfslog_CREATE2_fhargs, xdr_nfslog_createargs, xdr_nfslog_diropres,
sizeof (nfslog_createargs), sizeof (nfslog_diropres)},
{nfslog_REMOVE2_fhargs, xdr_nfslog_diropargs, xdr_nfsstat,
sizeof (nfslog_diropargs), sizeof (nfsstat)},
{nfslog_RENAME2_fhargs, xdr_nfslog_rnmargs, xdr_nfsstat,
sizeof (nfslog_rnmargs), sizeof (nfsstat)},
{nfslog_LINK2_fhargs, xdr_nfslog_linkargs, xdr_nfsstat,
sizeof (nfslog_linkargs), sizeof (nfsstat)},
{nfslog_SYMLINK2_fhargs, xdr_nfslog_symlinkargs, xdr_nfsstat,
sizeof (nfslog_symlinkargs), sizeof (nfsstat)},
{nfslog_CREATE2_fhargs, xdr_nfslog_createargs, xdr_nfslog_diropres,
sizeof (nfslog_createargs), sizeof (nfslog_diropres)},
{nfslog_REMOVE2_fhargs, xdr_nfslog_diropargs, xdr_nfsstat,
sizeof (nfslog_diropargs), sizeof (nfsstat)},
{nfslog_READDIR2_fhargs, xdr_nfslog_rddirargs, xdr_nfslog_rddirres,
sizeof (nfslog_rddirargs), sizeof (nfslog_rddirres)},
{nfslog_STATFS2_fhargs, xdr_fhandle, xdr_nfsstat,
sizeof (fhandle_t), sizeof (nfsstat)},
};
static struct nfsl_fh_proc_disp nfsl_fh_proc_v3[] = {
{nfslog_null_fhargs, xdr_void, xdr_void, 0, 0},
{nfslog_GETATTR3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_SETATTR3_fhargs, xdr_nfslog_SETATTR3args, xdr_nfsstat3,
sizeof (nfslog_SETATTR3args), sizeof (nfsstat3)},
{nfslog_LOOKUP3_fhargs, xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res,
sizeof (nfslog_diropargs3), sizeof (nfslog_LOOKUP3res)},
{nfslog_ACCESS3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_READLINK3_fhargs, xdr_nfs_fh3, xdr_nfslog_READLINK3res,
sizeof (nfs_fh3), sizeof (nfslog_READLINK3res)},
{nfslog_READ3_fhargs, xdr_nfslog_READ3args, xdr_nfslog_READ3res,
sizeof (nfslog_READ3args), sizeof (nfslog_READ3res)},
{nfslog_WRITE3_fhargs, xdr_nfslog_WRITE3args, xdr_nfslog_WRITE3res,
sizeof (nfslog_WRITE3args), sizeof (nfslog_WRITE3res)},
{nfslog_CREATE3_fhargs, xdr_nfslog_CREATE3args, xdr_nfslog_CREATE3res,
sizeof (nfslog_CREATE3args), sizeof (nfslog_CREATE3res)},
{nfslog_MKDIR3_fhargs, xdr_nfslog_MKDIR3args, xdr_nfslog_MKDIR3res,
sizeof (nfslog_MKDIR3args), sizeof (nfslog_MKDIR3res)},
{nfslog_SYMLINK3_fhargs, xdr_nfslog_SYMLINK3args,
xdr_nfslog_SYMLINK3res,
sizeof (nfslog_SYMLINK3args), sizeof (nfslog_SYMLINK3res)},
{nfslog_MKNOD3_fhargs, xdr_nfslog_MKNOD3args, xdr_nfslog_MKNOD3res,
sizeof (nfslog_MKNOD3args), sizeof (nfslog_MKNOD3res)},
{nfslog_REMOVE3_fhargs, xdr_nfslog_REMOVE3args, xdr_nfsstat3,
sizeof (nfslog_REMOVE3args), sizeof (nfsstat3)},
{nfslog_RMDIR3_fhargs, xdr_nfslog_RMDIR3args, xdr_nfsstat3,
sizeof (nfslog_RMDIR3args), sizeof (nfsstat3)},
{nfslog_RENAME3_fhargs, xdr_nfslog_RENAME3args, xdr_nfsstat3,
sizeof (nfslog_RENAME3args), sizeof (nfsstat3)},
{nfslog_LINK3_fhargs, xdr_nfslog_LINK3args, xdr_nfsstat3,
sizeof (nfslog_LINK3args), sizeof (nfsstat3)},
{nfslog_READDIR3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_READDIRPLUS3_fhargs,
xdr_nfslog_READDIRPLUS3args, xdr_nfslog_READDIRPLUS3res,
sizeof (nfslog_READDIRPLUS3args),
sizeof (nfslog_READDIRPLUS3res)},
{nfslog_FSSTAT3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_FSINFO3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_PATHCONF3_fhargs, xdr_nfs_fh3, xdr_nfsstat3,
sizeof (nfs_fh3), sizeof (nfsstat3)},
{nfslog_COMMIT3_fhargs, xdr_nfslog_COMMIT3args, xdr_nfsstat3,
sizeof (nfslog_COMMIT3args), sizeof (nfsstat3)},
};
static struct nfsl_fh_proc_disp nfsl_log_fh_proc_v1[] = {
{nfslog_null_fhargs, xdr_void, xdr_void, 0, 0},
{nfslog_SHARE_fhargs, xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres,
sizeof (nfslog_sharefsargs), sizeof (nfslog_sharefsres)},
{nfslog_UNSHARE_fhargs, xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres,
sizeof (nfslog_sharefsargs), sizeof (nfslog_sharefsres)},
{nfslog_LOOKUP3_fhargs, xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res,
sizeof (nfslog_diropargs3), sizeof (nfslog_LOOKUP3res)},
{nfslog_GETFH_fhargs, xdr_nfslog_getfhargs, xdr_nfsstat,
sizeof (nfslog_getfhargs), sizeof (nfsstat)},
};
static struct nfsl_fh_vers_disp nfsl_fh_vers_disptable[] = {
{sizeof (nfsl_fh_proc_v2) / sizeof (nfsl_fh_proc_v2[0]),
nfsl_fh_proc_v2},
{sizeof (nfsl_fh_proc_v3) / sizeof (nfsl_fh_proc_v3[0]),
nfsl_fh_proc_v3},
};
static struct nfsl_fh_vers_disp nfsl_log_fh_vers_disptable[] = {
{sizeof (nfsl_log_fh_proc_v1) / sizeof (nfsl_log_fh_proc_v1[0]),
nfsl_log_fh_proc_v1},
};
static struct nfsl_fh_prog_disp nfsl_fh_dispatch_table[] = {
{NFS_PROGRAM,
NFS_VERSMIN,
sizeof (nfsl_fh_vers_disptable) /
sizeof (nfsl_fh_vers_disptable[0]),
nfsl_fh_vers_disptable},
{NFSLOG_PROGRAM,
NFSLOG_VERSMIN,
sizeof (nfsl_log_fh_vers_disptable) /
sizeof (nfsl_log_fh_vers_disptable[0]),
nfsl_log_fh_vers_disptable},
};
static int nfsl_fh_dispatch_table_arglen =
sizeof (nfsl_fh_dispatch_table) /
sizeof (nfsl_fh_dispatch_table[0]);
extern int debug;
static void
sprint_fid(char *buf, uint_t buflen, const fhandle_t *fh)
{
int i;
uchar_t byte;
uint_t fhlen;
if (fh->fh_len > NFS_FHMAXDATA)
fhlen = NFS_FHMAXDATA;
else
fhlen = fh->fh_len;
assert(2 * fhlen < buflen);
for (i = 0; i < fhlen; i++) {
byte = fh->fh_data[i];
(void) sprintf(buf + 2 * i, "%02x", byte);
}
}
static void
fh_print_all_keys(char *fhpath, fhandle_t *fh)
{
if ((fhpath == NULL) || (fh == NULL) || (debug <= 1))
return;
(void) printf("\nBegin all database keys\n");
db_print_all_keys(fhpath, &fh->fh_fsid, stdout);
(void) printf("\nEnd all database keys\n");
}
#define FH_ADD(path, dfh, fh, name) \
fh_add(path, dfh, fh, name)
static int
fh_add(char *fhpath, fhandle_t *dfh, fhandle_t *fh, char *name)
{
uint_t flags = 0;
int error;
if (IS_DOT_FILENAME(name)) {
if (debug > 3) {
PRINT_FULL_DATA(stdout, "fh_add", dfh, fh, name,
" - no dot files")
}
return (0);
}
if (dfh && (memcmp(fh, dfh, NFS_FHSIZE) == 0)) {
flags |= EXPORT_POINT;
}
error = db_add(fhpath, dfh, name, fh, flags);
if (debug > 1) {
if (error != 0) {
(void) printf("db_add error %s:\n",
((error >= 0) ? strerror(error) : "Unknown"));
PRINT_FULL_DATA(stdout, "fh_add", dfh, fh, name, "")
} else if (debug > 2) {
PRINT_FULL_DATA(stdout, "fh_add", dfh, fh, name, "")
}
}
return (error);
}
static int
fh_compare(fhandle_t *fh1, fhandle_t *fh2)
{
if (memcmp(fh1, fh2, NFS_FHSIZE))
return (errno);
else
return (0);
}
static fhlist_ent *
fh_lookup(char *fhpath, fhandle_t *fh, fhlist_ent *fhrecp, int *errorp)
{
if (debug > 3) {
(void) printf("fh_lookup: fh ");
debug_opaque_print(stdout, fh, sizeof (*fh));
(void) printf("\n");
}
return (db_lookup(fhpath, fh, fhrecp, errorp));
}
static int
fh_remove_mc_link(char *fhpath, fhandle_t *dfh, char *name, char **pathp)
{
int error;
char *str, *str1;
if ((pathp == NULL) || (*pathp == NULL)) {
str = nfslog_get_path(dfh, name, fhpath, "remove_mc_link");
str1 = str;
} else {
str = *pathp;
str1 = NULL;
}
error = db_delete_link(fhpath, &public_fh, str);
if (str1 != NULL)
free(str1);
return (error);
}
static int
fh_remove(char *fhpath, fhandle_t *dfh, char *name, char **pathp)
{
if (IS_DOT_FILENAME(name)) {
if (debug > 2) {
PRINT_LINK_DATA(stdout, "fh_remove", dfh, name,
" - no dot files")
}
return (0);
}
if (debug > 2) {
PRINT_LINK_DATA(stdout, "fh_remove", dfh, name, "")
}
(void) fh_remove_mc_link(fhpath, dfh, name, pathp);
return (db_delete_link(fhpath, dfh, name));
}
static int
fh_rename(char *fhpath, fhandle_t *from_dfh, char *from_name, char **from_pathp,
fhandle_t *to_dfh, char *to_name)
{
if (debug > 2) {
PRINT_LINK_DATA(stdout, "fh_rename: from:", from_dfh,
from_name, "")
PRINT_LINK_DATA(stdout, "fh_rename: to :", to_dfh,
to_name, "")
}
if (IS_DOT_FILENAME(to_name)) {
if (debug > 2) {
(void) printf("to: no dot files\nDelete from: '%s'\n",
from_name);
}
return (fh_remove(fhpath, from_dfh, from_name, from_pathp));
} else if (IS_DOT_FILENAME(from_name)) {
if (debug > 2) {
(void) printf("rename - from: no dot files\n");
}
return (EINVAL);
}
(void) fh_remove_mc_link(fhpath, from_dfh, from_name, from_pathp);
return (db_rename_link(fhpath, from_dfh, from_name, to_dfh, to_name));
}
static fhlist_ent *
fh_lookup_link(char *fhpath, fhandle_t *dfh, fhandle_t *fh, char *name,
fhlist_ent *fhrecp, int *errorp)
{
fhlist_ent *in_fhrecp = fhrecp;
if ((name != NULL) && IS_DOT_FILENAME(name)) {
if (debug > 2) {
PRINT_FULL_DATA(stdout, "fh_lookup_link", dfh, fh, name,
" - no dot files\n")
}
*errorp = 0;
return (NULL);
}
if (debug > 3) {
PRINT_FULL_DATA(stdout, "fh_lookup_link", dfh, fh, name, "")
}
if (fh != NULL) {
fhrecp = db_lookup(fhpath, fh, fhrecp, errorp);
if (fhrecp == NULL) {
if (debug > 3)
(void) printf("fh_lookup_link: fh not found\n");
return (NULL);
}
if (((dfh == NULL) || !fh_compare(dfh, &fhrecp->dfh)) &&
((name == NULL) || (strcmp(name, fhrecp->name) == 0))) {
goto exit;
}
if (debug == 3) {
PRINT_FULL_DATA(stdout, "fh_lookup_link", dfh, fh,
name, "")
}
if (debug > 2) {
PRINT_LINK_DATA(stdout, "Different primary link",
&fhrecp->dfh, fhrecp->name, "")
}
if (fhrecp != in_fhrecp) {
free(fhrecp);
fhrecp = NULL;
}
}
if ((dfh == NULL) || (name == NULL)) {
if (debug > 2)
(void) printf("fh_lookup_link: invalid params\n");
*errorp = EINVAL;
return (NULL);
}
fhrecp = db_lookup_link(fhpath, dfh, name, fhrecp, errorp);
if (fhrecp == NULL) {
if (debug > 3)
(void) printf("fh_lookup_link: link not found: %s\n",
((*errorp >= 0) ? strerror(*errorp) : "Unknown"));
return (NULL);
}
if ((fh != NULL) && fh_compare(fh, &fhrecp->fh)) {
if (debug > 2) {
PRINT_FULL_DATA(stderr, "fh_lookup_link", dfh, fh,
name, "")
PRINT_LINK_DATA(stderr, "Different primary link",
&fhrecp->dfh, fhrecp->name, "")
}
if (fhrecp != in_fhrecp)
free(fhrecp);
*errorp = EINVAL;
return (NULL);
}
exit:
if (debug > 3)
(void) printf("lookup: found '%s' in fhtable\n", name);
*errorp = 0;
return (fhrecp);
}
static struct export_handle_cache *
find_fh_in_export_cache(fhandle_t *fh)
{
struct export_handle_cache *p;
for (p = exp_handle_cache; p != NULL; p = p->next) {
if (memcmp(fh, &p->fh, sizeof (*fh)) == 0)
break;
}
return (p);
}
static void
add_fh_to_export_cache(fhandle_t *fh, char *path)
{
struct export_handle_cache *new;
if ((new = malloc(sizeof (*new))) == NULL) {
syslog(LOG_ERR, gettext(
"add_fh_to_export_cache: alloc new for '%s' Error %s\n"),
((path != NULL) ? path : ""), strerror(errno));
return;
}
if (path != NULL) {
if ((new->name = malloc(strlen(path) + 1)) == NULL) {
syslog(LOG_ERR, gettext(
"add_fh_to_export_cache: alloc '%s'"
" Error %s\n"), path, strerror(errno));
free(new);
return;
}
(void) strcpy(new->name, path);
} else {
new->name = NULL;
}
(void) memcpy(&new->fh, fh, sizeof (*fh));
new->next = exp_handle_cache;
exp_handle_cache = new;
}
static char *
update_export_point(char *fhpath, fhandle_t *fh, char *path)
{
struct export_handle_cache *p;
if ((fh == NULL) || memcmp(&fh->fh_data, &fh->fh_xdata, fh->fh_len)) {
return (NULL);
}
if ((p = find_fh_in_export_cache(fh)) != NULL) {
if (debug > 2) {
PRINT_LINK_DATA(stdout, "update_export_point",
fh, ((p->name != NULL) ? p->name : ""), "");
}
if (p->name == NULL)
return (NULL);
if ((path == NULL) &&
((path = malloc(strlen(p->name) + 1)) == NULL)) {
syslog(LOG_ERR, gettext(
"update_export_point: malloc '%s' Error %s"),
p->name, strerror(errno));
return (NULL);
}
(void) strcpy(path, p->name);
return (path);
}
if ((path = get_export_path(fh, path)) == NULL) {
add_fh_to_export_cache(fh, NULL);
return (NULL);
}
if (debug > 2) {
PRINT_LINK_DATA(stdout, "update_export_point", fh, path, "")
}
if (FH_ADD(fhpath, fh, fh, path)) {
add_fh_to_export_cache(fh, path);
}
return (path);
}
static char *
get_export_path(fhandle_t *fh, char *path)
{
return (NULL);
}
static char *
fh_print_absolute(char *fhpath, fhandle_t *fh, char *name)
{
char *str, *rootname, parent[MAXPATHLEN];
int i, j, k, len, error;
fhlist_ent fhrec, *fhrecp;
fhandle_t prevfh;
int namelen;
if (debug > 3)
(void) printf("fh_print_absolute: input name '%s'\n",
((name != NULL) ? name : ""));
if ((name != NULL) && (name[0] == '/')) {
if ((str = strdup(name)) == NULL) {
syslog(LOG_ERR, gettext(
"fh_print_absolute: strdup '%s' error %s\n"),
name, strerror(errno));
}
return (str);
}
namelen = ((name != NULL) ? strlen(name) + 2 : 0);
parent[0] = '\0';
(void) memcpy((void *) &prevfh, (void *) fh, sizeof (*fh));
fh = &prevfh;
while ((fhrecp = fh_lookup(fhpath, fh, &fhrec, &error)) != NULL &&
!(fhrecp->flags & (EXPORT_POINT | PUBLIC_PATH))) {
if (debug > 3) {
(void) printf("fh_print_absolute: name '%s'%s\n",
fhrecp->name,
((fhrecp->flags & EXPORT_POINT) ? "root" : ""));
}
if (memcmp(&prevfh, &fhrecp->dfh, sizeof (*fh)) == 0) {
if (debug > 1) {
(void) printf(
"fh_print_absolute: fhrec loop:\n");
debug_opaque_print(stdout, fhrecp,
fhrecp->reclen);
}
break;
}
(void) strcat(parent, "/");
(void) strcat(parent, fhrecp->name);
(void) memcpy(&prevfh, &fhrecp->dfh, sizeof (fhrecp->dfh));
}
assert(fh == &prevfh);
if (fhrecp != NULL) {
rootname = fhrecp->name;
} else {
rootname = update_export_point(
fhpath, fh, &parent[strlen(parent) + 1]);
}
if (rootname != NULL) {
len = strlen(rootname) + 2;
} else {
len = 2 * (NFS_FHMAXDATA + fh->fh_len);
}
len = ROUNDUP32(len + namelen + strlen(parent));
if ((str = malloc(len)) == NULL) {
syslog(LOG_ERR, gettext(
"fh_print_absolute: malloc %d error %s\n"),
len, strerror(errno));
return (NULL);
}
if (rootname != NULL) {
(void) strcpy(str, rootname);
} else {
sprint_fid(str, len, fh);
}
for (k = strlen(str), i = strlen(parent); (k < len) && (i >= 0); i--) {
for (j = i; (j >= 0) && (parent[j] != '/'); j--);
if (j < 0)
break;
(void) strcpy(&str[k], &parent[j]);
k += strlen(&str[k]);
parent[j] = '\0';
}
if ((name != NULL) && ((k + namelen) <= len)) {
str[k] = '/';
(void) strcpy(&str[k + 1], name);
}
if (debug > 3)
(void) printf("fh_print_absolute: path '%s'\n", str);
return (str);
}
static struct nfsl_fh_proc_disp *
nfslog_find_fh_dispatch(nfslog_request_record *logrec)
{
nfslog_record_header *logrechdr = &logrec->re_header;
struct nfsl_fh_prog_disp *progtable;
struct nfsl_fh_vers_disp *verstable;
int i, vers;
for (i = 0; (i < nfsl_fh_dispatch_table_arglen) &&
(logrechdr->rh_prognum != nfsl_fh_dispatch_table[i].nfsl_dis_prog);
i++);
if (i >= nfsl_fh_dispatch_table_arglen) {
return (NULL);
}
progtable = &nfsl_fh_dispatch_table[i];
vers = logrechdr->rh_version - progtable->nfsl_dis_versmin;
verstable = &progtable->nfsl_dis_vers_table[vers];
return (&verstable->nfsl_dis_proc_table[logrechdr->rh_procnum]);
}
static void
nfslog_null_fhargs(caddr_t *nfsl_args, caddr_t *nfsl_res,
char *fhpath, char **pathp1, char **pathp2)
{
*pathp1 = NULL;
*pathp2 = NULL;
}
static void
nfslog_LOOKUP_calc(fhandle_t *dfh, char *name, fhandle_t *fh,
char *fhpath, char **pathp1, char **pathp2, char *str)
{
int error;
fhlist_ent fhrec;
char *name1 = NULL;
if (fh == &public_fh) {
if (error = FH_ADD(fhpath, fh, fh, name)) {
syslog(LOG_ERR, gettext(
"%s: Add Public fs '%s' failed: %s\n"),
str, name,
((error >= 0) ? strerror(error) : "Unknown"));
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, NULL, fhpath, str);
*pathp2 = NULL;
}
return;
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, str);
*pathp2 = NULL;
}
if (dfh == &public_fh) {
if (pathp1 != NULL) {
name = *pathp1;
} else {
name = nfslog_get_path(dfh, name, fhpath, str);
name1 = name;
}
}
if (fh_lookup_link(fhpath, dfh, fh, name, &fhrec, &error) != NULL) {
if (name1 != NULL)
free(name1);
return;
}
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"%s: Add fh for '%s' failed: %s\n"), str,
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
if (name1 != NULL)
free(name1);
}
static void
nfslog_GETATTR2_fhargs(fhandle_t *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nGETATTR2: fh ");
debug_opaque_print(stdout, args, sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE2(args),
NULL, fhpath, "getattr2");
*pathp2 = NULL;
}
}
static void
nfslog_SETATTR2_fhargs(nfslog_setattrargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nSETATTR2: fh ");
debug_opaque_print(stdout, &args->saa_fh,
sizeof (args->saa_fh));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE2(&args->saa_fh),
NULL, fhpath, "setattr2");
*pathp2 = NULL;
}
}
static void
nfslog_LOOKUP2_fhargs(nfslog_diropargs *args, nfslog_diropres *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
dfh = &args->da_fhandle;
name = args->da_name;
if (debug > 2) {
if (res->dr_status == NFS_OK)
fh = &res->nfslog_diropres_u.dr_ok.drok_fhandle;
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nLOOKUP2",
dfh, fh, name, "")
if (res->dr_status != NFS_OK)
(void) printf("status %d\n", res->dr_status);
}
dfh = NFSLOG_GET_FHANDLE2(dfh);
if ((dfh == &public_fh) && (name[0] == '\x80')) {
name = &name[1];
}
if (res->dr_status != NFS_OK) {
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "lookup2");
*pathp2 = NULL;
}
return;
}
fh = NFSLOG_GET_FHANDLE2(&res->nfslog_diropres_u.dr_ok.drok_fhandle);
nfslog_LOOKUP_calc(dfh, name, fh, fhpath, pathp1, pathp2, "Lookup2");
}
static void
nfslog_READLINK2_fhargs(fhandle_t *args, nfslog_rdlnres *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREADLINK2: fh ");
debug_opaque_print(stdout, args, sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE2(args),
NULL, fhpath, "readlink2");
*pathp2 = NULL;
}
}
static void
nfslog_READ2_fhargs(nfslog_nfsreadargs *args, nfslog_rdresult *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREAD2: fh ");
debug_opaque_print(stdout, &args->ra_fhandle,
sizeof (args->ra_fhandle));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(
NFSLOG_GET_FHANDLE2(&args->ra_fhandle),
NULL, fhpath, "read2");
*pathp2 = NULL;
}
}
static void
nfslog_WRITE2_fhargs(nfslog_writeargs *args, nfslog_writeresult *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nWRITE2: fh ");
debug_opaque_print(stdout, &args->waargs_fhandle,
sizeof (args->waargs_fhandle));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(
NFSLOG_GET_FHANDLE2(&args->waargs_fhandle),
NULL, fhpath, "write2");
*pathp2 = NULL;
}
}
static void
nfslog_CREATE2_fhargs(nfslog_createargs *args, nfslog_diropres *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
name = args->ca_da.da_name;
dfh = &args->ca_da.da_fhandle;
if (debug > 2) {
if (res->dr_status == NFS_OK)
fh = &res->nfslog_diropres_u.dr_ok.drok_fhandle;
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nCREATE2",
dfh, fh, name, "")
if (res->dr_status != NFS_OK)
(void) printf("status %d\n", res->dr_status);
}
dfh = NFSLOG_GET_FHANDLE2(dfh);
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "create2");
*pathp2 = NULL;
}
if (res->dr_status != NFS_OK)
return;
fh = NFSLOG_GET_FHANDLE2(&res->nfslog_diropres_u.dr_ok.drok_fhandle);
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Create2: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_REMOVE2_fhargs(nfslog_diropargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh;
int error;
name = args->da_name;
dfh = &args->da_fhandle;
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nREMOVE2", dfh, name, "")
if (*res != NFS_OK)
(void) printf("status %d\n", *res);
}
dfh = NFSLOG_GET_FHANDLE2(dfh);
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "remove2");
*pathp2 = NULL;
}
if (*res != NFS_OK)
return;
if (error = fh_remove(fhpath, dfh, name, pathp1)) {
syslog(LOG_ERR, gettext("Remove2: '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_RENAME2_fhargs(nfslog_rnmargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *from_name, *to_name;
fhandle_t *from_dfh, *to_dfh;
int error;
from_name = args->rna_from.da_name;
from_dfh = &args->rna_from.da_fhandle;
to_name = args->rna_to.da_name;
to_dfh = &args->rna_to.da_fhandle;
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nRENAME2: from",
from_dfh, from_name, "")
PRINT_LINK_DATA(stdout, "RENAME2: to ", to_dfh,
to_name, "")
if (*res != NFS_OK)
(void) printf("status %d\n", *res);
}
from_dfh = NFSLOG_GET_FHANDLE2(from_dfh);
to_dfh = NFSLOG_GET_FHANDLE2(to_dfh);
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(from_dfh, from_name, fhpath,
"rename2 from");
*pathp2 = nfslog_get_path(to_dfh, to_name, fhpath,
"rename2 to");
}
if (*res != NFS_OK)
return;
if (error = fh_rename(fhpath, from_dfh, from_name, pathp1,
to_dfh, to_name)) {
syslog(LOG_ERR, gettext(
"Rename2: Update from '%s' to '%s' failed: %s\n"),
from_name, to_name,
((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_LINK2_fhargs(nfslog_linkargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
fh = &args->la_from;
name = args->la_to.da_name;
dfh = &args->la_to.da_fhandle;
if (debug > 2) {
PRINT_FULL_DATA(stdout, "=============\nLINK2",
dfh, fh, name, "")
if (*res != NFS_OK)
(void) printf("status %d\n", *res);
}
dfh = NFSLOG_GET_FHANDLE2(dfh);
fh = NFSLOG_GET_FHANDLE2(fh);
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(fh, NULL, fhpath, "link2 from");
*pathp2 = nfslog_get_path(dfh, name, fhpath, "link2 to");
}
if (*res != NFS_OK)
return;
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Link2: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_SYMLINK2_fhargs(nfslog_symlinkargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh;
name = args->sla_from.da_name;
dfh = &args->sla_from.da_fhandle;
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nSYMLINK2",
dfh, name, "")
}
dfh = NFSLOG_GET_FHANDLE2(dfh);
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "symlink2");
*pathp2 = NULL;
}
}
static void
nfslog_READDIR2_fhargs(nfslog_rddirargs *args, nfslog_rddirres *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREADDIR2: fh ");
debug_opaque_print(stdout, &args->rda_fh,
sizeof (args->rda_fh));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE2(&args->rda_fh),
NULL, fhpath, "readdir2");
*pathp2 = NULL;
}
}
static void
nfslog_STATFS2_fhargs(fhandle_t *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nSTATFS2: fh ");
debug_opaque_print(stdout, args, sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE2(args),
NULL, fhpath, "statfs2");
*pathp2 = NULL;
}
}
static void
nfslog_GETATTR3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nGETATTR3: fh ");
debug_opaque_print(stdout, args, sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args), NULL,
fhpath, "getattr3");
*pathp2 = NULL;
}
}
static void
nfslog_SETATTR3_fhargs(nfslog_SETATTR3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nSETATTR3: fh ");
debug_opaque_print(stdout, &args->object,
sizeof (args->object));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(&args->object),
NULL, fhpath, "setattr3");
*pathp2 = NULL;
}
}
static void
nfslog_LOOKUP3_fhargs(nfslog_diropargs3 *args, nfslog_LOOKUP3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
name = args->name;
dfh = NFSLOG_GET_FHANDLE3(&args->dir);
if (debug > 2) {
if (res->status == NFS3_OK)
fh = NFSLOG_GET_FHANDLE3(
&res->nfslog_LOOKUP3res_u.object);
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nLOOKUP3",
dfh, fh, name, "")
if (res->status != NFS3_OK)
(void) printf("status %d\n", res->status);
}
if ((dfh == &public_fh) && (name[0] == '\x80')) {
name = &name[1];
}
if (res->status != NFS3_OK) {
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "lookup3");
*pathp2 = NULL;
}
return;
}
fh = NFSLOG_GET_FHANDLE3(&res->nfslog_LOOKUP3res_u.object);
nfslog_LOOKUP_calc(dfh, name, fh, fhpath, pathp1, pathp2, "Lookup3");
}
static void
nfslog_ACCESS3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nACCESS3: fh ");
debug_opaque_print(stdout, args,
sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args),
NULL, fhpath, "access3");
*pathp2 = NULL;
}
}
static void
nfslog_READLINK3_fhargs(nfs_fh3 *args, nfslog_READLINK3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREADLINK3: fh ");
debug_opaque_print(stdout, args, sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args), NULL,
fhpath, "readlink3");
*pathp2 = NULL;
}
}
static void
nfslog_READ3_fhargs(nfslog_READ3args *args, nfslog_READ3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREAD3: fh ");
debug_opaque_print(stdout, &args->file,
sizeof (args->file));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(&args->file),
NULL, fhpath, "read3");
*pathp2 = NULL;
}
}
static void
nfslog_WRITE3_fhargs(nfslog_WRITE3args *args, nfslog_WRITE3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nWRITE3: fh ");
debug_opaque_print(stdout, &args->file,
sizeof (args->file));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(&args->file),
NULL, fhpath, "write3");
*pathp2 = NULL;
}
}
static void
nfslog_CREATE3_fhargs(nfslog_CREATE3args *args, nfslog_CREATE3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
name = args->where.name;
dfh = NFSLOG_GET_FHANDLE3(&args->where.dir);
if (debug > 2) {
if (res->status == NFS3_OK)
fh = NFSLOG_GET_FHANDLE3(
&res->nfslog_CREATE3res_u.ok.obj.handle);
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nCREATE3",
dfh, fh, name, "")
if (res->status != NFS3_OK)
(void) printf("status %d\n", res->status);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "create3");
*pathp2 = NULL;
}
if ((res->status != NFS3_OK) ||
!res->nfslog_CREATE3res_u.ok.obj.handle_follows)
return;
fh = NFSLOG_GET_FHANDLE3(&res->nfslog_CREATE3res_u.ok.obj.handle);
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Create3: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_MKDIR3_fhargs(nfslog_MKDIR3args *args, nfslog_MKDIR3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
name = args->where.name;
dfh = NFSLOG_GET_FHANDLE3(&args->where.dir);
if (debug > 2) {
if (res->status == NFS3_OK)
fh = NFSLOG_GET_FHANDLE3(
&res->nfslog_MKDIR3res_u.obj.handle);
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nMKDIR3",
dfh, fh, name, "")
if (res->status != NFS3_OK)
(void) printf("status %d\n", res->status);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "mkdir3");
*pathp2 = NULL;
}
if ((res->status != NFS3_OK) ||
!res->nfslog_MKDIR3res_u.obj.handle_follows)
return;
fh = NFSLOG_GET_FHANDLE3(&res->nfslog_MKDIR3res_u.obj.handle);
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Mkdir3: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_REMOVE3_fhargs(nfslog_REMOVE3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh;
int error;
name = args->object.name;
dfh = NFSLOG_GET_FHANDLE3(&args->object.dir);
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nREMOVE3", dfh, name, "")
if (*res != NFS3_OK)
(void) printf("status %d\n", *res);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "remove3");
*pathp2 = NULL;
}
if (*res != NFS3_OK)
return;
if (error = fh_remove(fhpath, dfh, name, pathp1)) {
syslog(LOG_ERR, gettext("Remove3: '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_RMDIR3_fhargs(nfslog_RMDIR3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh;
int error;
name = args->object.name;
dfh = NFSLOG_GET_FHANDLE3(&args->object.dir);
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nRMDIR3", dfh, name, "")
if (*res != NFS3_OK)
(void) printf("status %d\n", *res);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "rmdir3");
*pathp2 = NULL;
}
if (*res != NFS3_OK)
return;
if (error = fh_remove(fhpath, dfh, name, pathp1)) {
syslog(LOG_ERR, gettext("Rmdir3: '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_RENAME3_fhargs(nfslog_RENAME3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *from_name, *to_name;
fhandle_t *from_dfh, *to_dfh;
int error;
from_name = args->from.name;
from_dfh = NFSLOG_GET_FHANDLE3(&args->from.dir);
to_name = args->to.name;
to_dfh = NFSLOG_GET_FHANDLE3(&args->to.dir);
if (debug > 2) {
PRINT_LINK_DATA(stdout, "=============\nRENAME3: from",
from_dfh, from_name, "")
PRINT_LINK_DATA(stdout, "=============\nRENAME3: to ",
to_dfh, to_name, "")
if (*res != NFS3_OK)
(void) printf("status %d\n", *res);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(from_dfh, from_name, fhpath,
"rename3 from");
*pathp2 = nfslog_get_path(to_dfh, to_name, fhpath,
"rename3 to");
}
if (*res != NFS3_OK)
return;
if (error = fh_rename(fhpath, from_dfh, from_name, pathp1,
to_dfh, to_name)) {
syslog(LOG_ERR, gettext(
"Rename3: Update from '%s' to '%s' failed: %s\n"),
from_name, to_name,
((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_LINK3_fhargs(nfslog_LINK3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
fh = NFSLOG_GET_FHANDLE3(&args->file);
name = args->link.name;
dfh = NFSLOG_GET_FHANDLE3(&args->link.dir);
if (debug > 2) {
PRINT_FULL_DATA(stdout, "=============\nLINK3",
dfh, fh, name, "")
if (*res != NFS3_OK)
(void) printf("status %d\n", *res);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(fh, NULL, fhpath, "link3 from");
*pathp2 = nfslog_get_path(dfh, name, fhpath, "link3 to");
}
if (*res != NFS3_OK)
return;
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Link3: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_MKNOD3_fhargs(nfslog_MKNOD3args *args, nfslog_MKNOD3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
name = args->where.name;
dfh = NFSLOG_GET_FHANDLE3(&args->where.dir);
if (debug > 2) {
if (res->status == NFS3_OK)
fh = NFSLOG_GET_FHANDLE3(
&res->nfslog_MKNOD3res_u.obj.handle);
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nMKNOD3",
dfh, fh, name, "")
if (res->status != NFS3_OK)
(void) printf("status %d\n", res->status);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "mknod3");
*pathp2 = NULL;
}
if ((res->status != NFS3_OK) ||
!res->nfslog_MKNOD3res_u.obj.handle_follows)
return;
fh = NFSLOG_GET_FHANDLE3(&res->nfslog_MKNOD3res_u.obj.handle);
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext("Mknod3: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_SYMLINK3_fhargs(nfslog_SYMLINK3args *args, nfslog_SYMLINK3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
int error;
name = args->where.name;
dfh = NFSLOG_GET_FHANDLE3(&args->where.dir);
if (debug > 2) {
if (res->status == NFS3_OK)
fh = NFSLOG_GET_FHANDLE3(
&res->nfslog_SYMLINK3res_u.obj.handle);
else
fh = NULL;
PRINT_FULL_DATA(stdout, "=============\nSYMLINK3",
dfh, fh, name, "")
if (res->status != NFS3_OK)
(void) printf("status %d\n", res->status);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(dfh, name, fhpath, "symlink3");
*pathp2 = NULL;
}
if ((res->status != NFS3_OK) ||
!res->nfslog_SYMLINK3res_u.obj.handle_follows)
return;
fh = NFSLOG_GET_FHANDLE3(&res->nfslog_SYMLINK3res_u.obj.handle);
if (error = FH_ADD(fhpath, dfh, fh, name)) {
syslog(LOG_ERR, gettext(
"Symlink3: Add fh for '%s' failed: %s\n"),
name, ((error >= 0) ? strerror(error) : "Unknown"));
}
}
static void
nfslog_READDIR3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nREADDIR3: fh ");
debug_opaque_print(stdout, args,
sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args),
NULL, fhpath, "readdir3");
*pathp2 = NULL;
}
}
static void
nfslog_READDIRPLUS3_fhargs(nfslog_READDIRPLUS3args *args,
nfslog_READDIRPLUS3res *res,
char *fhpath, char **pathp1, char **pathp2)
{
char *name;
fhandle_t *dfh, *fh;
nfslog_entryplus3 *ep;
if (debug > 2) {
(void) printf("=============\nREADDIRPLUS3: fh ");
debug_opaque_print(stdout, &args->dir,
sizeof (args->dir));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(&args->dir),
NULL, fhpath, "readdirplus3");
*pathp2 = NULL;
}
if (res->status == NFS3_OK) {
dfh = NFSLOG_GET_FHANDLE3(&args->dir);
for (ep = res->nfslog_READDIRPLUS3res_u.ok.reply.entries;
ep != NULL;
ep = ep->nextentry) {
name = ep->name;
fh = NFSLOG_GET_FHANDLE3(&ep->name_handle.handle);
nfslog_LOOKUP_calc(dfh, name, fh,
fhpath, NULL, NULL,
"ReaddirPlus3");
}
}
}
static void
nfslog_FSSTAT3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nFSSTAT3: fh ");
debug_opaque_print(stdout, args,
sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args), NULL,
fhpath, "fsstat3");
*pathp2 = NULL;
}
}
static void
nfslog_FSINFO3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nFSINFO3: fh ");
debug_opaque_print(stdout, args,
sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args), NULL,
fhpath, "fsinfo3");
*pathp2 = NULL;
}
}
static void
nfslog_PATHCONF3_fhargs(nfs_fh3 *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nPATHCONF3: fh ");
debug_opaque_print(stdout, args,
sizeof (*args));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(args), NULL,
fhpath, "pathconf3");
*pathp2 = NULL;
}
}
static void
nfslog_COMMIT3_fhargs(nfslog_COMMIT3args *args, nfsstat3 *res,
char *fhpath, char **pathp1, char **pathp2)
{
if (debug > 2) {
(void) printf("=============\nCOMMIT3: fh ");
debug_opaque_print(stdout, &args->file,
sizeof (args->file));
(void) printf("\n");
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(NFSLOG_GET_FHANDLE3(&args->file),
NULL, fhpath, "commit3");
*pathp2 = NULL;
}
}
static void
nfslog_SHARE_fhargs(nfslog_sharefsargs *args, nfslog_sharefsres *res,
char *fhpath, char **pathp1, char **pathp2)
{
fhlist_ent fhrec;
fhandle_t *fh;
int error;
if (debug > 2) {
(void) printf(
"=============\nSHARE: name '%s', fh ", args->sh_path);
debug_opaque_print(stdout, &args->sh_fh_buf,
sizeof (fhandle_t));
(void) printf("\n");
}
fh = &args->sh_fh_buf;
bcopy(fh->fh_xdata, fh->fh_data, fh->fh_xlen);
if (debug > 10) {
fh_print_all_keys(fhpath, fh);
}
if (fh_lookup_link(fhpath, fh, fh,
args->sh_path, &fhrec, &error) == NULL) {
if (error = FH_ADD(fhpath, fh, fh, args->sh_path)) {
syslog(LOG_ERR, gettext(
"Share: Add fh for '%s' failed: %s\n"),
args->sh_path, ((error >= 0) ?
strerror(error) : "Unknown"));
}
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(fh, NULL, fhpath, "share");
*pathp2 = NULL;
}
}
static void
nfslog_UNSHARE_fhargs(nfslog_sharefsargs *args, nfslog_sharefsres *res,
char *fhpath, char **pathp1, char **pathp2)
{
fhandle_t *fh;
int error;
if (debug > 2) {
(void) printf("=============\nUNSHARE: name '%s', fh ",
args->sh_path);
debug_opaque_print(stdout, &args->sh_fh_buf,
sizeof (fhandle_t));
(void) printf("\n");
}
fh = &args->sh_fh_buf;
bcopy(fh->fh_xdata, fh->fh_data, fh->fh_xlen);
if (debug > 10) {
fh_print_all_keys(fhpath, fh);
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(fh, NULL, fhpath, "share");
*pathp2 = NULL;
}
if (error = fh_remove(fhpath, fh, args->sh_path, pathp1)) {
syslog(LOG_ERR, gettext("Unshare: '%s' failed: %s\n"),
args->sh_path, ((error >= 0) ? strerror(error) :
"Unknown"));
}
}
static void
nfslog_GETFH_fhargs(nfslog_getfhargs *args, nfsstat *res,
char *fhpath, char **pathp1, char **pathp2)
{
fhlist_ent fhrec;
fhandle_t *fh;
int error;
if (debug > 2) {
(void) printf("=============\nGETFH3: name '%s', fh ",
args->gfh_path);
debug_opaque_print(stdout, &args->gfh_fh_buf,
sizeof (fhandle_t));
(void) printf("\n");
}
fh = &args->gfh_fh_buf;
if (debug > 10) {
fh_print_all_keys(fhpath, fh);
}
if (fh_lookup_link(fhpath, fh, fh,
args->gfh_path, &fhrec, &error) == NULL) {
if (error = FH_ADD(fhpath, fh, fh, args->gfh_path)) {
syslog(LOG_ERR, gettext(
"Getfh: Add fh for '%s' failed: %s\n"),
args->gfh_path, ((error >= 0) ?
strerror(error) : "Unknown"));
}
}
if (pathp1 != NULL) {
*pathp1 = nfslog_get_path(fh, NULL, fhpath, "getfh");
*pathp2 = NULL;
}
}
char *
nfslog_get_path(fhandle_t *fh, char *name, char *fhpath, char *prtstr)
{
char *pathp = fh_print_absolute(fhpath, fh, name);
if (debug > 3) {
(void) printf(" %s: path '%s', fh ", prtstr, pathp);
debug_opaque_print(stdout, fh, sizeof (*fh));
(void) printf("\n");
}
return (pathp);
}
int
nfslog_process_fh_rec(struct nfslog_lr *lrp, char *fhpath, char **pathp1,
char **pathp2, bool_t return_path)
{
struct nfsl_fh_proc_disp *disp;
nfslog_request_record *logrec = &lrp->log_record;
nfslog_record_header *logrechdr = &logrec->re_header;
if ((disp = nfslog_find_fh_dispatch(logrec)) != NULL) {
logrec->re_rpc_arg = calloc(1, disp->args_size);
if (!(*disp->xdr_args)(&lrp->xdrs, logrec->re_rpc_arg)) {
free(logrec->re_rpc_arg);
logrec->re_rpc_arg = NULL;
syslog(LOG_ERR, gettext("argument decode failed"));
return (FALSE);
}
lrp->xdrargs = disp->xdr_args;
logrec->re_rpc_res = calloc(1, disp->res_size);
if (!(*disp->xdr_res)(&lrp->xdrs, logrec->re_rpc_res)) {
free(logrec->re_rpc_res);
logrec->re_rpc_res = NULL;
syslog(LOG_ERR, gettext("results decode failed"));
return (FALSE);
}
lrp->xdrres = disp->xdr_res;
if (return_path) {
(*disp->nfsl_dis_args)(logrec->re_rpc_arg,
logrec->re_rpc_res, fhpath, pathp1, pathp2);
} else {
if ((logrechdr->rh_version == NFS_VERSION &&
logrechdr->rh_procnum == RFS_LINK) ||
(logrechdr->rh_version == NFS_V3 &&
logrechdr->rh_procnum == NFSPROC3_LINK)) {
(*disp->nfsl_dis_args)(logrec->re_rpc_arg,
logrec->re_rpc_res,
fhpath, pathp1, pathp2);
} else {
(*disp->nfsl_dis_args)(logrec->re_rpc_arg,
logrec->re_rpc_res,
fhpath, NULL, NULL);
}
}
return (TRUE);
} else {
syslog(LOG_ERR, gettext("procedure unknown"));
return (FALSE);
}
}