/* * 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) 1999 by Sun Microsystems, Inc. * All rights reserved. */ /* * Code to maintain the runtime and on-disk filehandle mapping table for * nfslog. */ #include #include #include #include #include #include #include #include #include #include #include #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); /* * export handle cache */ 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); /* * NFS VERSION 2 */ /* * Functions for updating the fhtable for fhtoppath and for returning * the absolute pathname */ 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 **); /* * NFS VERSION 3 * * Functions for updating the fhtable for fhtoppath */ 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 **); /* * NFSLOG VERSION 1 * * Functions for updating the fhtable for fhtoppath */ 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 **); /* * Define the actions taken per prog/vers/proc: * * In some cases, the nl types are the same as the nfs types and a simple * bcopy should suffice. Rather that define tens of identical procedures, * simply define these to bcopy. Similarly this takes care of different * procs that use same parameter struct. */ static struct nfsl_fh_proc_disp nfsl_fh_proc_v2[] = { /* * NFS VERSION 2 */ /* RFS_NULL = 0 */ {nfslog_null_fhargs, xdr_void, xdr_void, 0, 0}, /* RFS_GETATTR = 1 */ {nfslog_GETATTR2_fhargs, xdr_fhandle, xdr_nfsstat, sizeof (fhandle_t), sizeof (nfsstat)}, /* RFS_SETATTR = 2 */ {nfslog_SETATTR2_fhargs, xdr_nfslog_setattrargs, xdr_nfsstat, sizeof (nfslog_setattrargs), sizeof (nfsstat)}, /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */ {nfslog_null_fhargs, xdr_void, xdr_void, 0, 0}, /* RFS_LOOKUP = 4 */ {nfslog_LOOKUP2_fhargs, xdr_nfslog_diropargs, xdr_nfslog_diropres, sizeof (nfslog_diropargs), sizeof (nfslog_diropres)}, /* RFS_READLINK = 5 */ {nfslog_READLINK2_fhargs, xdr_fhandle, xdr_nfslog_rdlnres, sizeof (fhandle_t), sizeof (nfslog_rdlnres)}, /* RFS_READ = 6 */ {nfslog_READ2_fhargs, xdr_nfslog_nfsreadargs, xdr_nfslog_rdresult, sizeof (nfslog_nfsreadargs), sizeof (nfslog_rdresult)}, /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */ {nfslog_null_fhargs, xdr_void, xdr_void, 0, 0}, /* RFS_WRITE = 8 */ {nfslog_WRITE2_fhargs, xdr_nfslog_writeargs, xdr_nfslog_writeresult, sizeof (nfslog_writeargs), sizeof (nfslog_writeresult)}, /* RFS_CREATE = 9 */ {nfslog_CREATE2_fhargs, xdr_nfslog_createargs, xdr_nfslog_diropres, sizeof (nfslog_createargs), sizeof (nfslog_diropres)}, /* RFS_REMOVE = 10 */ {nfslog_REMOVE2_fhargs, xdr_nfslog_diropargs, xdr_nfsstat, sizeof (nfslog_diropargs), sizeof (nfsstat)}, /* RFS_RENAME = 11 */ {nfslog_RENAME2_fhargs, xdr_nfslog_rnmargs, xdr_nfsstat, sizeof (nfslog_rnmargs), sizeof (nfsstat)}, /* RFS_LINK = 12 */ {nfslog_LINK2_fhargs, xdr_nfslog_linkargs, xdr_nfsstat, sizeof (nfslog_linkargs), sizeof (nfsstat)}, /* RFS_SYMLINK = 13 */ {nfslog_SYMLINK2_fhargs, xdr_nfslog_symlinkargs, xdr_nfsstat, sizeof (nfslog_symlinkargs), sizeof (nfsstat)}, /* RFS_MKDIR = 14 */ {nfslog_CREATE2_fhargs, xdr_nfslog_createargs, xdr_nfslog_diropres, sizeof (nfslog_createargs), sizeof (nfslog_diropres)}, /* RFS_RMDIR = 15 */ {nfslog_REMOVE2_fhargs, xdr_nfslog_diropargs, xdr_nfsstat, sizeof (nfslog_diropargs), sizeof (nfsstat)}, /* RFS_READDIR = 16 */ {nfslog_READDIR2_fhargs, xdr_nfslog_rddirargs, xdr_nfslog_rddirres, sizeof (nfslog_rddirargs), sizeof (nfslog_rddirres)}, /* RFS_STATFS = 17 */ {nfslog_STATFS2_fhargs, xdr_fhandle, xdr_nfsstat, sizeof (fhandle_t), sizeof (nfsstat)}, }; /* * NFS VERSION 3 */ static struct nfsl_fh_proc_disp nfsl_fh_proc_v3[] = { /* RFS_NULL = 0 */ {nfslog_null_fhargs, xdr_void, xdr_void, 0, 0}, /* RFS3_GETATTR = 1 */ {nfslog_GETATTR3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_SETATTR = 2 */ {nfslog_SETATTR3_fhargs, xdr_nfslog_SETATTR3args, xdr_nfsstat3, sizeof (nfslog_SETATTR3args), sizeof (nfsstat3)}, /* RFS3_LOOKUP = 3 */ {nfslog_LOOKUP3_fhargs, xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, sizeof (nfslog_diropargs3), sizeof (nfslog_LOOKUP3res)}, /* RFS3_ACCESS = 4 */ {nfslog_ACCESS3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_READLINK = 5 */ {nfslog_READLINK3_fhargs, xdr_nfs_fh3, xdr_nfslog_READLINK3res, sizeof (nfs_fh3), sizeof (nfslog_READLINK3res)}, /* RFS3_READ = 6 */ {nfslog_READ3_fhargs, xdr_nfslog_READ3args, xdr_nfslog_READ3res, sizeof (nfslog_READ3args), sizeof (nfslog_READ3res)}, /* RFS3_WRITE = 7 */ {nfslog_WRITE3_fhargs, xdr_nfslog_WRITE3args, xdr_nfslog_WRITE3res, sizeof (nfslog_WRITE3args), sizeof (nfslog_WRITE3res)}, /* RFS3_CREATE = 8 */ {nfslog_CREATE3_fhargs, xdr_nfslog_CREATE3args, xdr_nfslog_CREATE3res, sizeof (nfslog_CREATE3args), sizeof (nfslog_CREATE3res)}, /* RFS3_MKDIR = 9 */ {nfslog_MKDIR3_fhargs, xdr_nfslog_MKDIR3args, xdr_nfslog_MKDIR3res, sizeof (nfslog_MKDIR3args), sizeof (nfslog_MKDIR3res)}, /* RFS3_SYMLINK = 10 */ {nfslog_SYMLINK3_fhargs, xdr_nfslog_SYMLINK3args, xdr_nfslog_SYMLINK3res, sizeof (nfslog_SYMLINK3args), sizeof (nfslog_SYMLINK3res)}, /* RFS3_MKNOD = 11 */ {nfslog_MKNOD3_fhargs, xdr_nfslog_MKNOD3args, xdr_nfslog_MKNOD3res, sizeof (nfslog_MKNOD3args), sizeof (nfslog_MKNOD3res)}, /* RFS3_REMOVE = 12 */ {nfslog_REMOVE3_fhargs, xdr_nfslog_REMOVE3args, xdr_nfsstat3, sizeof (nfslog_REMOVE3args), sizeof (nfsstat3)}, /* RFS3_RMDIR = 13 */ {nfslog_RMDIR3_fhargs, xdr_nfslog_RMDIR3args, xdr_nfsstat3, sizeof (nfslog_RMDIR3args), sizeof (nfsstat3)}, /* RFS3_RENAME = 14 */ {nfslog_RENAME3_fhargs, xdr_nfslog_RENAME3args, xdr_nfsstat3, sizeof (nfslog_RENAME3args), sizeof (nfsstat3)}, /* RFS3_LINK = 15 */ {nfslog_LINK3_fhargs, xdr_nfslog_LINK3args, xdr_nfsstat3, sizeof (nfslog_LINK3args), sizeof (nfsstat3)}, /* RFS3_READDIR = 16 */ {nfslog_READDIR3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_READDIRPLUS = 17 */ {nfslog_READDIRPLUS3_fhargs, xdr_nfslog_READDIRPLUS3args, xdr_nfslog_READDIRPLUS3res, sizeof (nfslog_READDIRPLUS3args), sizeof (nfslog_READDIRPLUS3res)}, /* RFS3_FSSTAT = 18 */ {nfslog_FSSTAT3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_FSINFO = 19 */ {nfslog_FSINFO3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_PATHCONF = 20 */ {nfslog_PATHCONF3_fhargs, xdr_nfs_fh3, xdr_nfsstat3, sizeof (nfs_fh3), sizeof (nfsstat3)}, /* RFS3_COMMIT = 21 */ {nfslog_COMMIT3_fhargs, xdr_nfslog_COMMIT3args, xdr_nfsstat3, sizeof (nfslog_COMMIT3args), sizeof (nfsstat3)}, }; /* * NFSLOG VERSION 1 */ static struct nfsl_fh_proc_disp nfsl_log_fh_proc_v1[] = { /* NFSLOG_NULL = 0 */ {nfslog_null_fhargs, xdr_void, xdr_void, 0, 0}, /* NFSLOG_SHARE = 1 */ {nfslog_SHARE_fhargs, xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, sizeof (nfslog_sharefsargs), sizeof (nfslog_sharefsres)}, /* NFSLOG_UNSHARE = 2 */ {nfslog_UNSHARE_fhargs, xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, sizeof (nfslog_sharefsargs), sizeof (nfslog_sharefsres)}, /* NFSLOG_LOOKUP3 = 3 */ {nfslog_LOOKUP3_fhargs, xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, sizeof (nfslog_diropargs3), sizeof (nfslog_LOOKUP3res)}, /* NFSLOG_GETFH = 4 */ {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; /* * print the fid into the given string as a series of hex digits. * XXX Ideally, we'd like to just convert the filehandle into an i-number, * but the fid encoding is a little tricky (see nfs_fhtovp() and * ufs_vget()) and may be private to UFS. */ static void sprint_fid(char *buf, uint_t buflen, const fhandle_t *fh) { int i; uchar_t byte; uint_t fhlen; /* * If the filehandle somehow got corrupted, only print the part * that makes sense. */ 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) /* * Add the filehandle "fh", which has the name "name" and lives in * directory "dfh", to the table "fhlist". "fhlist" will be updated if the * entry is added to the front of the list. * Return 0 for success, error code otherwise. */ 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)) { /* we don't insert these to the database but not an error */ 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; } /* Add to database */ 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); } /* * fh_compare returns 0 if the file handles match, error code otherwise */ static int fh_compare(fhandle_t *fh1, fhandle_t *fh2) { if (memcmp(fh1, fh2, NFS_FHSIZE)) return (errno); else return (0); } /* * Try to find the filehandle "fh" in the table. Returns 0 and the * corresponding table entry if found, error otherwise. * If successfull and fhrecpp is non-null then *fhrecpp points to the * returned record. If *fhrecpp was initially null, that record had * been malloc'd and must be freed by caller. */ 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)); } /* * Remove the mc link if exists when removing a regular link. * Return 0 for success, error code otherwise. */ static int fh_remove_mc_link(char *fhpath, fhandle_t *dfh, char *name, char **pathp) { int error; char *str, *str1; /* Delete the multi-component path if exists */ 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); } /* * Remove the link entry from the fh table. * Return 0 for success, error code otherwise. */ static int fh_remove(char *fhpath, fhandle_t *dfh, char *name, char **pathp) { /* * disconnect element from list * * Remove the link entry for the file. Remove fh entry if last link. */ if (IS_DOT_FILENAME(name)) { /* we don't insert these to the database but not an error */ 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, "") } /* Delete the multi-component path if exists */ (void) fh_remove_mc_link(fhpath, dfh, name, pathp); return (db_delete_link(fhpath, dfh, name)); } /* * fh_rename - renames a link in the database (adds the new one if from link * did not exist). * Return 0 for success, error code otherwise. */ 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 any of these are dot files (should not happen), the rename * becomes a "delete" or "add" operation because the dot files * don't get in the database */ if (IS_DOT_FILENAME(to_name)) { /* it is just a delete op */ 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)) { /* we don't insert these to the database */ if (debug > 2) { (void) printf("rename - from: no dot files\n"); } /* can't insert the target, because don't have a handle */ return (EINVAL); } /* Delete the multi-component path if exists */ (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)); } /* * fh_lookup_link - search the fhtable for the link defined by (dfh,name,fh). * Return 0 and set *fhrecpp to the fhlist item corresponding to it if found, * or error if not found. * Possible configurations: * 1. dfh, fh, name are all non-null: Only exact match accepted. * 2. dfh,name non-null, fh null: return first match found. * 3. fh,name non-null, dfh null: return first match found. * 3. fh non-null, dfh, name null: return first match found. * If successfull and fhrecpp is non-null then *fhrecpp points to the * returned record. If *fhrecpp was initially null, that record had * been malloc'd and must be freed by caller. */ 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)) { /* we don't insert these to the database but not an error */ 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, "") } /* Add to database */ 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); } /* Check if name and dfh match, if not search link */ if (((dfh == NULL) || !fh_compare(dfh, &fhrecp->dfh)) && ((name == NULL) || (strcmp(name, fhrecp->name) == 0))) { /* found it */ goto exit; } /* Found the primary record, but it's a different link */ if (debug == 3) { /* Only log if >2 but already printed */ PRINT_FULL_DATA(stdout, "fh_lookup_link", dfh, fh, name, "") } if (debug > 2) { PRINT_LINK_DATA(stdout, "Different primary link", &fhrecp->dfh, fhrecp->name, "") } /* can now free the record unless it was supplied by caller */ if (fhrecp != in_fhrecp) { free(fhrecp); fhrecp = NULL; } } /* If here, we must search by link */ 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 all args supplied, check if an exact match */ 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); } /* * Export handle cache is maintained if we see an export handle that either * cannot have the path for it determined, or we failed store it. * Usually the path of an export handle can be identified in the NFSLOGTAB * and since every path for that filesystem will be affected, it's worth * caching the ones we had problem identifying. */ /* * find_fh_in_export_cache - given an export fh, find it in the cache and * return the handle */ 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; } /* * update_export_point - called when the path for fh cannot be determined. * In the past it called get_export_path() to get the name of the * export point given a filehandle. This was a hack, since there's no * reason why the filehandle should be lost. * * If a match is found, insert the path to the database. * Return the inserted fhrecp is found, * and NULL if not. If it is an exported fs but not in the list, log a * error. * If input fhrecp is non-null, it is a valid address for result, * otherwise malloc it. */ 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)) { /* either null fh or not the root of a shared directory */ return (NULL); } /* Did we already see (and fail) this one? */ if ((p = find_fh_in_export_cache(fh)) != NULL) { /* Found it! */ if (debug > 2) { PRINT_LINK_DATA(stdout, "update_export_point", fh, ((p->name != NULL) ? p->name : ""), ""); } if (p->name == NULL) return (NULL); /* * We should not normally be here - only add to cache if * fh_add failed. */ 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); } /* Found it! */ if (debug > 2) { PRINT_LINK_DATA(stdout, "update_export_point", fh, path, "") } if (FH_ADD(fhpath, fh, fh, path)) { /* cache this handle so we don't repeat the search */ add_fh_to_export_cache(fh, path); } return (path); } /* * HACK!!! To get rid of get_export_path() use */ /* ARGSUSED */ static char * get_export_path(fhandle_t *fh, char *path) { return (NULL); } /* * Return the absolute pathname for the filehandle "fh", using the mapping * table "fhlist". The caller must free the return string. * name is an optional dir component name, to be appended at the end * (if name is non-null, the function assumes the fh is the parent directory) * * Note: The original code was recursive, which was much more elegant but * ran out of stack... */ 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 starts with '/' we are done */ 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'; /* remember the last filehandle we've seen */ (void) memcpy((void *) &prevfh, (void *) fh, sizeof (*fh)); fh = &prevfh; /* dump all names in reverse order */ 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) { /* dfh == prevfh but not an export point */ 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); /* remember the last filehandle we've seen */ (void) memcpy(&prevfh, &fhrecp->dfh, sizeof (fhrecp->dfh)); } assert(fh == &prevfh); if (fhrecp != NULL) { rootname = fhrecp->name; } else { /* Check if export point, just in case... */ /* There should be enough room in parent, leave the '\0' */ rootname = update_export_point( fhpath, fh, &parent[strlen(parent) + 1]); } /* Now need to reverse the order */ if (rootname != NULL) { /* *fhrecp is the export point */ len = strlen(rootname) + 2; } else { len = 2 * (NFS_FHMAXDATA + fh->fh_len); /* fid instead */ } 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); } /* first put the export point path in */ if (rootname != NULL) { /* *fhrecp is the export point */ (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); } /* * nfslog_find_fh_dispatch - get the dispatch struct for this request */ 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; /* prog struct */ struct nfsl_fh_vers_disp *verstable; /* version struct */ int i, vers; /* Find prog element - search because can't use prog as array index */ 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) { /* program not logged */ /* not an error */ return (NULL); } progtable = &nfsl_fh_dispatch_table[i]; /* Find vers element - no validity check - if here it's valid vers */ vers = logrechdr->rh_version - progtable->nfsl_dis_versmin; verstable = &progtable->nfsl_dis_vers_table[vers]; /* Find proc element - no validity check - if here it's valid proc */ return (&verstable->nfsl_dis_proc_table[logrechdr->rh_procnum]); } /* ARGSUSED */ static void nfslog_null_fhargs(caddr_t *nfsl_args, caddr_t *nfsl_res, char *fhpath, char **pathp1, char **pathp2) { *pathp1 = NULL; *pathp2 = NULL; } /* * nfslog_LOOKUP_calc - called by both lookup3 and lookup2. Handles the * mclookup as well as normal lookups. */ /* ARGSUSED */ 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) { /* a fake lookup to inform us of the public fs path */ 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 public fh mclookup, then insert complete path */ 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) { /* link already in table */ if (name1 != NULL) free(name1); return; } /* A new link so add it */ 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); } /* * NFS VERSION 2 */ /* Functions for updating the fhtable for fhtoppath */ /* * nfslog_GETATTR2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_SETATTR2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_LOOKUP2_fhargs - search the table to ensure we have not added this * one already. Note that if the response status was anything but okay, * there is no fh to check... */ /* ARGSUSED */ 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')) { /* special mclookup */ 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"); } /* * nfslog_READLINK2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_READ2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_WRITE2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_CREATE2_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new file handle so add it */ 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")); } } /* * nfslog_REMOVE2_fhargs - if the operation succeeded, remove the link from * the fhtable. */ /* ARGSUSED */ 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) /* remove failed so nothing to update */ return; if (error = fh_remove(fhpath, dfh, name, pathp1)) { syslog(LOG_ERR, gettext("Remove2: '%s' failed: %s\n"), name, ((error >= 0) ? strerror(error) : "Unknown")); } } /* * nfsl_RENAME2_fhargs - updates the dfh and name fields for the given fh * to change them to the new name. */ /* ARGSUSED */ 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) /* rename failed so nothing to update */ return; /* Rename the link in the database */ 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")); } } /* * nfslog_LINK2_fhargs - adds link name and fh to fhlist. Note that as a * result we may have more than one name for an fh. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new link so add it, have fh_add find the link count */ 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")); } } /* * nfslog_SYMLINK2_fhargs - adds symlink name and fh to fhlist if fh returned. */ /* ARGSUSED */ 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; } } /* * nfslog_READDIR2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_STATFS2_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * NFS VERSION 3 */ /* Functions for updating the fhtable for fhtoppath */ /* * nfslog_GETATTR3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_SETATTR3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_LOOKUP3_fhargs - search the table to ensure we have not added this * one already. Note that if the response status was anything but okay, * there is no fh to check... */ /* ARGSUSED */ 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')) { /* special mclookup */ 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"); } /* * nfslog_ACCESS3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_READLINK3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_READ3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_WRITE3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_CREATE3_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new file handle so add it */ 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")); } } /* * nfslog_MKDIR3_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new file handle so add it */ 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")); } } /* * nfslog_REMOVE3_fhargs - if the operation succeeded, remove the link from * the fhtable. */ /* ARGSUSED */ 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) /* remove failed so nothing to update */ return; if (error = fh_remove(fhpath, dfh, name, pathp1)) { syslog(LOG_ERR, gettext("Remove3: '%s' failed: %s\n"), name, ((error >= 0) ? strerror(error) : "Unknown")); } } /* * nfslog_RMDIR3_fhargs - if the operation succeeded, remove the link from * the fhtable. */ /* ARGSUSED */ 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) /* rmdir failed so nothing to update */ return; if (error = fh_remove(fhpath, dfh, name, pathp1)) { syslog(LOG_ERR, gettext("Rmdir3: '%s' failed: %s\n"), name, ((error >= 0) ? strerror(error) : "Unknown")); } } /* * nfslog_RENAME3_fhargs - if the operation succeeded, update the existing * fhtable entry to point to new dir and name. */ /* ARGSUSED */ 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) /* rename failed so nothing to update */ 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")); } } /* * nfslog_LINK3_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* link failed so nothing to add */ return; /* A new link so add it, have fh_add find link count */ 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")); } } /* * nfslog_MKNOD3_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new file handle so add it */ 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")); } } /* * nfslog_SYMLINK3_fhargs - if the operation succeeded, we are sure there can * be no such link in the fhtable, so just add it. */ /* ARGSUSED */ 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) /* no returned fh so nothing to add */ return; /* A new file handle so add it */ 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")); } } /* * nfslog_READDIR3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_READDIRPLUS3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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); /* * Loop through the fh/name pair and add them * to the mappings. */ 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"); } } } /* * nfslog_FSSTAT3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_FSINFO3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_PATHCONF3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * nfslog_COMMIT3_fhargs - updates path1 but no fhtable changes */ /* ARGSUSED */ 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; } } /* * NFSLOG VERSION 1 */ /* * nfslog_SHARE_fhargs - adds export path and handle to fhlist */ /* ARGSUSED */ 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; /* * This bcopy is done because the fh_data for the export/share directory * is not meaningful with respect to the database keys. Therefore, we * copy the export or fh_xdata fid to the fh_data so that a reasonable * entry will be added in the data base. */ bcopy(fh->fh_xdata, fh->fh_data, fh->fh_xlen); /* If debug print the database */ 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; } } /* * nfslog_UNSHARE_fhargs - remove export path and handle from fhlist */ /* ARGSUSED */ 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; /* * This bcopy is done because the fh_data for the export/share directory * is not meaningful with respect to the database keys. Therefore, we * copy the export or fh_xdata fid to the fh_data so that a reasonable * entry will be added in the data base. */ bcopy(fh->fh_xdata, fh->fh_data, fh->fh_xlen); /* If debug print the database */ 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")); } } /* ARGSUSED */ 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 print the database */ 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; } } /* * Exported function */ /* * nfslog_get_path - gets the path for this file. fh must be supplied, * name may be null. If name is supplied, fh is assumed to be a directory * filehandle, with name as its component. fhpath is the generic path for the * fhtopath table and prtstr is the name of the caller (for debug purposes). * Returns the malloc'd path. The caller must free it later. */ 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); } /* * nfslog_process_fh_rec - updates the fh table based on the rpc req * Return 0 for success, error otherwise. If success return the path * for the input file handle(s) if so indicated. */ 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) { /* * Allocate space for the args and results and decode */ 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); } /* used later for free of data structures */ 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); } /* used later for free of data structures */ lrp->xdrres = disp->xdr_res; /* * Process the operation within the context of the file handle * mapping process */ 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); } }