nfs-ganesha 1.4

commands_NFS.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005 
00006  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00007  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00008  *
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 3 of the License, or (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023  *
00024  * ---------------------------------------
00025  */
00026 
00137 #ifdef HAVE_CONFIG_H
00138 #include "config.h"
00139 #endif
00140 
00141 #ifdef _SOLARIS
00142 #include "solaris_port.h"
00143 #endif
00144 
00145 #include "ganesha_rpc.h"
00146 #include "fsal.h"
00147 #include "cache_inode.h"
00148 #include "commands.h"
00149 #include "abstract_mem.h"
00150 #include "Getopt.h"
00151 #include "cmd_nfstools.h"
00152 #include "cmd_tools.h"
00153 #include "nfs_file_handle.h"
00154 #include "nfs_core.h"
00155 #include <ctype.h>
00156 #include <unistd.h>
00157 #include <pwd.h>
00158 #include <string.h>
00159 #include "cmd_tools.h"
00160 
00161 writeverf3 NFS3_write_verifier;
00162 
00163 /* Function used for debugging */
00164 #ifdef _DEBUG_NFS_SHELL
00165 void print_nfs_res(nfs_res_t * p_res)
00166 {
00167   int index;
00168   for(index = 0; index < sizeof(nfs_res_t); index++)
00169     {
00170       if((index + 1) % 32 == 0)
00171         printf("%02X\n", ((char *)p_res)[index]);
00172       else
00173         printf("%02X.", ((char *)p_res)[index]);
00174     }
00175   printf("\n");
00176 }
00177 #endif
00178 
00179 /* --------------- INTERNAL FH3 REPRESENTATION ---------------- */
00180 /* used for keeping handle value after
00181  * freeing nfs res.
00182  */
00183 typedef struct shell_fh3__
00184 {
00185   u_int data_len;
00186   char data_val[NFS3_FHSIZE];
00187 } shell_fh3_t;
00188 
00189 static void set_shell_fh3(shell_fh3_t * p_int_fh3, nfs_fh3 * p_nfshdl)
00190 {
00191   p_int_fh3->data_len = p_nfshdl->data.data_len;
00192   memcpy(p_int_fh3->data_val, p_nfshdl->data.data_val, p_nfshdl->data.data_len);
00193 }
00194 
00195 static void set_nfs_fh3(nfs_fh3 * p_nfshdl, shell_fh3_t * p_int_fh3)
00196 {
00197   p_nfshdl->data.data_len = p_int_fh3->data_len;
00198   p_nfshdl->data.data_val = p_int_fh3->data_val;
00199 }
00200 
00201 /* ------------------------- END ------------------------------ */
00202 
00203 /* The cache hash table (defined in "commands_Cache_inode.c") */
00204 extern hash_table_t *fh_to_cache_entry_ht;
00205 
00206 extern cache_inode_client_parameter_t cache_client_param;
00207 extern cache_content_client_parameter_t datacache_client_param;
00208 
00209 /* NFS layer initialization status*/
00210 static int is_nfs_layer_initialized = FALSE;
00211 
00212 /* Global variable: export list */
00213 exportlist_t exportlist[128];
00214 exportlist_t *pexportlist = exportlist;
00215 
00216 /* Global variable: local host name */
00217 static char localmachine[256];
00218 
00219 /* thread specific variables */
00220 
00221 typedef struct cmdnfs_thr_info__
00222 {
00223 
00224   int is_thread_init;
00225 
00226   /* export context : on for each thread,
00227    * on order to make it possible for them
00228    * to access different filesets.
00229    */
00230   fsal_export_context_t exp_context;
00231 
00233   fsal_op_context_t context;
00234 
00235   /* AuthUnix_params for this thread */
00236   struct authunix_parms authunix_struct;
00237 
00239   cache_content_client_t dc_client;
00240 
00241   /* info for advanced commands (pwd, ls, cd, ...) */
00242   int is_mounted_path;
00243 
00244   shell_fh3_t mounted_path_hdl;
00245   char mounted_path[NFS2_MAXPATHLEN];
00246 
00247   shell_fh3_t current_path_hdl;
00248   char current_path[NFS2_MAXPATHLEN];
00249 
00250 } cmdnfs_thr_info_t;
00251 
00252 /* pthread key to manage thread specific configuration */
00253 
00254 static pthread_key_t thread_key;
00255 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00256 
00257 /* init pthtread_key for current thread */
00258 
00259 static void init_keys(void)
00260 {
00261   time_t ServerBootTime = time(NULL);
00262 
00263   if(pthread_key_create(&thread_key, NULL) == -1)
00264     printf("Error %d creating pthread key for thread %p : %s\n",
00265            errno, (caddr_t) pthread_self(), strerror(errno));
00266 
00267   memset(NFS3_write_verifier, 0, sizeof(writeverf3));
00268   memcpy(NFS3_write_verifier, &ServerBootTime, sizeof(time_t));
00269 
00270   return;
00271 }                               /* init_keys */
00272 
00273 cmdnfs_thr_info_t *GetNFSClient()
00274 {
00275   cmdnfs_thr_info_t *p_thr_info;
00276 
00277   /* first, we init the keys if this is the first time */
00278   if(pthread_once(&once_key, init_keys) != 0)
00279     {
00280       printf("Error %d calling pthread_once for thread %p : %s\n",
00281              errno, (caddr_t) pthread_self(), strerror(errno));
00282       return NULL;
00283     }
00284 
00285   p_thr_info = (cmdnfs_thr_info_t *) pthread_getspecific(thread_key);
00286 
00287   /* we allocate the thread context if this is the first time */
00288   if(p_thr_info == NULL)
00289     {
00290 
00291       /* allocates thread structure */
00292       p_thr_info = gsh_malloc(sizeof(cmdnfs_thr_info_t));
00293 
00294       /* panic !!! */
00295       if(p_thr_info == NULL)
00296         {
00297           printf("%p:commands_NFS: Not enough memory\n", (caddr_t) pthread_self());
00298           return NULL;
00299         }
00300 
00301       /* Clean thread context */
00302 
00303       memset(p_thr_info, 0, sizeof(cmdnfs_thr_info_t));
00304 
00305       p_thr_info->is_thread_init = FALSE;
00306       p_thr_info->is_mounted_path = FALSE;
00307 
00308       /* set the specific value */
00309       pthread_setspecific(thread_key, (void *)p_thr_info);
00310 
00311     }
00312 
00313   return p_thr_info;
00314 
00315 }                               /* GetNFSClient */
00316 
00317 int InitNFSClient(cmdnfs_thr_info_t * p_thr_info)
00318 {
00319   uid_t uid;
00320   fsal_status_t st;
00321   struct passwd *pw_struct;
00322 
00323   if(p_thr_info == NULL)
00324     return -1;
00325 
00326   if(p_thr_info->is_thread_init == TRUE)
00327     return 0;
00328 
00329   /* for the moment, create export context for root fileset */
00330   st = FSAL_BuildExportContext(&p_thr_info->exp_context, NULL, NULL);
00331 
00332   if(FSAL_IS_ERROR(st))
00333     {
00334       printf
00335           ("%p:commands_NFS: Error %d initializing credentials for thread (FSAL_InitThreadCred)\n",
00336            (caddr_t) pthread_self(), st.major);
00337       return st.major;
00338     }
00339 
00340   /* initialize FSAL credential for this thread */
00341 
00342   st = FSAL_InitClientContext(&p_thr_info->context);
00343 
00344   if(FSAL_IS_ERROR(st))
00345     {
00346       printf
00347           ("%p:commands_NFS: Error %d initializing credentials for thread (FSAL_InitThreadCred)\n",
00348            (caddr_t) pthread_self(), st.major);
00349       return st.major;
00350     }
00351 
00352   uid = getuid();
00353   pw_struct = getpwuid(uid);
00354 
00355   if(pw_struct == NULL)
00356     {
00357       printf("commands_NFS: Unknown user %u\n", uid);
00358       return errno;
00359     }
00360 
00361   st = FSAL_GetClientContext(&p_thr_info->context, &p_thr_info->exp_context,
00362                              uid, pw_struct->pw_gid, NULL, 0);
00363 
00364   if(FSAL_IS_ERROR(st))
00365     {
00366       printf("%p:commands_NFS: Error %d getting contexte for uid %d (FSAL_GetUserCred)\n",
00367              (caddr_t) pthread_self(), st.major, uid);
00368       return st.major;
00369     }
00370 
00371   p_thr_info->authunix_struct.aup_machname = localmachine;
00372   p_thr_info->authunix_struct.aup_uid = uid;
00373   p_thr_info->authunix_struct.aup_gid = getgid();
00374   p_thr_info->authunix_struct.aup_len = 0; 
00376   /* Init the cache content client */
00377   if(cache_content_client_init(&p_thr_info->dc_client, datacache_client_param, "") != 0)
00378     return 1;
00379 
00380   p_thr_info->is_thread_init = TRUE;
00381 
00382   return 0;
00383 
00384 }                               /* InitNFSClient */
00385 
00386 void nfs_layer_SetLogLevel(int log_lvl)
00387 {
00388 
00389   /* Nothing to do. */
00390   return;
00391 
00392 }
00393 
00394 static void getopt_init()
00395 {
00396   /* disables getopt error message */
00397   Opterr = 0;
00398   /* reinits getopt processing */
00399   Optind = 1;
00400 }
00401 
00402 int nfs_init(char *filename, int flag_v, FILE * output)
00403 {
00404   config_file_t config_file;
00405   int rc;
00406 
00407   nfs_param.cache_layers_param.cache_content_client_param.nb_prealloc_entry = 100;
00408   nfs_param.cache_layers_param.cache_content_client_param.flush_force_fsal = 1;
00409   nfs_param.cache_layers_param.cache_content_client_param.max_fd = 20;
00410   nfs_param.cache_layers_param.cache_content_client_param.use_fd_cache = 0;
00411   nfs_param.cache_layers_param.cache_content_client_param.retention = 60;
00412   strcpy(nfs_param.cache_layers_param.cache_content_client_param.cache_dir,
00413          "/tmp/ganesha.datacache");
00414 
00415   /* Parse config file */
00416 
00417   config_file = config_ParseFile(filename);
00418 
00419   if(!config_file)
00420     {
00421       fprintf(output, "nfs_init: Error parsing %s: %s\n", filename, config_GetErrorMsg());
00422       return -1;
00423     }
00424 
00425   if((rc =
00426       cache_content_read_conf_client_parameter(config_file,
00427                                                &nfs_param.cache_layers_param.
00428                                                cache_content_client_param)) !=
00429      CACHE_CONTENT_SUCCESS)
00430     {
00431       fprintf(output, "nfs_init: Error %d reading cache content parameters.\n", -rc);
00432       return -1;
00433     }
00434 
00435   /* Read export list from file */
00436 
00437   rc = ReadExports(config_file, &pexportlist);
00438 
00439   if(rc < 0)
00440     {
00441       fprintf(output, "nfs_init: Error %d while parsing exports file.\n", -rc);
00442       return -1;
00443     }
00444 
00445   /* initalize export entries */
00446   if((rc = nfs_export_create_root_entry(pexportlist)) != TRUE)
00447     {
00448       fprintf(output, "nfs_init: Error %d initializing root entries, exiting...", -rc);
00449       return -1;
00450     }
00451 
00452   /* geting the hostname */
00453   rc = gethostname(localmachine, sizeof(localmachine));
00454   if(rc != 0)
00455     {
00456       fprintf(output, "nfs_init: Error %d while getting hostname.\n", rc);
00457       return -1;
00458     }
00459 
00462   is_nfs_layer_initialized = TRUE;
00463 
00464   if(flag_v)
00465     fprintf(output, "\tNFS layer successfully initialized.\n");
00466 
00467   return 0;
00468 }
00469 
00471 int fn_nfs_init(int argc,       /* IN : number of args in argv */
00472                 char **argv,    /* IN : arg list               */
00473                 FILE * output   /* IN : output stream          */
00474     )
00475 {
00476   int flag_v = 0;
00477   int flag_h = 0;
00478   int err_flag = 0;
00479   int option;
00480   char *filename = NULL;
00481   int rc;
00482 
00483   char format[] = "hv";
00484 
00485   const char help_nfs_init[] =
00486 /*  "usage: nfs_init [options] <ganesha_config_file>\n"*/
00487       "usage: nfs_init [options] <ganesha_config_file>\n"
00488       "options :\n" "\t-h print this help\n" "\t-v verbose mode\n";
00489 
00490   if(is_nfs_layer_initialized != FALSE)
00491     {
00492       fprintf(output, "\tNFS layer is already initialized.\n");
00493       return 0;
00494     }
00495 
00496   /* analysing options */
00497   getopt_init();
00498   while((option = Getopt(argc, argv, format)) != -1)
00499     {
00500       switch (option)
00501         {
00502         case 'v':
00503           if(flag_v)
00504             fprintf(output,
00505                     "nfs_init: warning: option 'v' has been specified more than once.\n");
00506           else
00507             flag_v++;
00508           break;
00509 
00510         case 'h':
00511           if(flag_h)
00512             fprintf(output,
00513                     "nfs_init: warning: option 'h' has been specified more than once.\n");
00514           else
00515             flag_h++;
00516           break;
00517 
00518         case '?':
00519           fprintf(output, "nfs_init: unknown option : %c\n", Optopt);
00520           err_flag++;
00521           break;
00522         }                       /* switch */
00523     }                           /* while */
00524 
00525   if(flag_h)
00526     {
00527       fprintf(output, help_nfs_init);
00528       return 0;
00529     }
00530 
00531   /* verifies mandatory argument */
00532   if(Optind != (argc - 1))
00533     {
00534       /* too much or not enough arguments */
00535       err_flag++;
00536     }
00537   else
00538     filename = argv[Optind];
00539 
00540   if(err_flag)
00541     {
00542       fprintf(output, help_nfs_init);
00543       return -1;
00544     }
00545 
00546   rc = nfs_init(filename, flag_v, output);
00547 
00548   return rc;
00549 
00550 }                               /* fn_nfs_init */
00551 
00553 int fn_MNT1_command(int argc,   /* IN : number of args in argv */
00554                     char **argv,        /* IN : arg list               */
00555                     FILE * output       /* IN : output stream          */
00556     )
00557 {
00558 
00559   cmdnfs_funcdesc_t *funcdesc = mnt1_funcdesc;
00560 
00561   nfs_arg_t nfs_arg;
00562   nfs_res_t nfs_res;
00563   struct svc_req req;
00564   int rc;
00565   cmdnfs_thr_info_t *p_thr_info = NULL;
00566 
00567   if(is_nfs_layer_initialized != TRUE)
00568     {
00569       fprintf(output, "\tNFS layer not initialized.\n");
00570       return -1;
00571     }
00572 
00573   p_thr_info = GetNFSClient();
00574 
00575   if(p_thr_info->is_thread_init != TRUE)
00576     {
00577       if((rc = InitNFSClient(p_thr_info)))
00578         {
00579           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
00580           return -1;
00581         }
00582     }
00583 
00584   while(funcdesc->func_name != NULL)
00585     {
00586       if(!strcmp(funcdesc->func_name, argv[0]))
00587         {
00588 
00589           /* encoding args */
00590 
00591           if(funcdesc->func_encode(CMDNFS_ENCODE,
00592                                    argc - 1, argv + 1,
00593                                    0, NULL, (caddr_t) & nfs_arg) == FALSE)
00594             {
00595               fprintf(output, "%s: bad arguments.\n", argv[0]);
00596               fprintf(output, "Usage: %s\n", funcdesc->func_help);
00597               return -1;
00598             }
00599 
00600           /* preparing request identifier */
00601           req.rq_prog = MOUNTPROG;
00602           req.rq_vers = MOUNT_V1;
00603 
00604           req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
00605 
00606           /* nfs call */
00607 
00608           rc = funcdesc->func_call(&nfs_arg,
00609                                    pexportlist,
00610                                    &(p_thr_info->context),
00611                                    &(p_thr_info->client), &req, &nfs_res);
00612 
00613           /* freeing args */
00614 
00615           funcdesc->func_encode(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
00616 
00617           /* decoding output */
00618 
00619 #ifdef _DEBUG_NFS_SHELL
00620           printf("MNTv1: RETURNED STRUCTURE:\n");
00621           print_nfs_res(&nfs_res);
00622 #endif
00623 
00624           funcdesc->func_decode(CMDNFS_DECODE, 0, NULL, 0, output, (caddr_t) & nfs_res);
00625 
00626           funcdesc->func_free(&nfs_res);
00627 
00628           /* returning status */
00629           return rc;
00630 
00631         }
00632 
00633       /* pointer to the next cmdnfs_funcdesc_t */
00634       funcdesc++;
00635     }
00636 
00637   fprintf(output, "%s: command not found in MNT1 protocol.\n", argv[0]);
00638   return -1;
00639 
00640 }                               /* fn_MNT1_command */
00641 
00643 int fn_MNT3_command(int argc,   /* IN : number of args in argv */
00644                     char **argv,        /* IN : arg list               */
00645                     FILE * output       /* IN : output stream          */
00646     )
00647 {
00648 
00649   cmdnfs_funcdesc_t *funcdesc = mnt3_funcdesc;
00650 
00651   nfs_arg_t nfs_arg;
00652   nfs_res_t nfs_res;
00653   struct svc_req req;
00654   int rc;
00655   cmdnfs_thr_info_t *p_thr_info = NULL;
00656 
00657   if(is_nfs_layer_initialized != TRUE)
00658     {
00659       fprintf(output, "\tNFS layer not initialized.\n");
00660       return -1;
00661     }
00662 
00663   p_thr_info = GetNFSClient();
00664 
00665   if(p_thr_info->is_thread_init != TRUE)
00666     {
00667       if((rc = InitNFSClient(p_thr_info)))
00668         {
00669           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
00670           return -1;
00671         }
00672     }
00673 
00674   while(funcdesc->func_name != NULL)
00675     {
00676       if(!strcmp(funcdesc->func_name, argv[0]))
00677         {
00678 
00679           /* encoding args */
00680 
00681           if(funcdesc->func_encode(CMDNFS_ENCODE,
00682                                    argc - 1, argv + 1,
00683                                    0, NULL, (caddr_t) & nfs_arg) == FALSE)
00684             {
00685               fprintf(output, "%s: bad arguments.\n", argv[0]);
00686               fprintf(output, "Usage: %s\n", funcdesc->func_help);
00687               return -1;
00688             }
00689 
00690           /* preparing request identifier */
00691           req.rq_prog = MOUNTPROG;
00692           req.rq_vers = MOUNT_V3;
00693 
00694           req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
00695 
00696           /* nfs call */
00697 
00698           rc = funcdesc->func_call(&nfs_arg,
00699                                    pexportlist,
00700                                    &(p_thr_info->context),
00701                                    &(p_thr_info->client), &req, &nfs_res);
00702 
00703           /* freeing args */
00704 
00705           funcdesc->func_encode(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
00706 
00707           /* decoding output */
00708 #ifdef _DEBUG_NFS_SHELL
00709           printf("MNTv3: RETURNED STRUCTURE:\n");
00710           print_nfs_res(&nfs_res);
00711 #endif
00712 
00713           funcdesc->func_decode(CMDNFS_DECODE, 0, NULL, 0, output, (caddr_t) & nfs_res);
00714 
00715           funcdesc->func_free(&nfs_res);
00716 
00717           /* returning status */
00718           return rc;
00719 
00720         }
00721 
00722       /* pointer to the next cmdnfs_funcdesc_t */
00723       funcdesc++;
00724     }
00725 
00726   fprintf(output, "%s: command not found in MNT3 protocol.\n", argv[0]);
00727   return -1;
00728 
00729 }
00730 
00732 int fn_NFS2_command(int argc,   /* IN : number of args in argv */
00733                     char **argv,        /* IN : arg list               */
00734                     FILE * output       /* IN : output stream          */
00735     )
00736 {
00737 
00738   cmdnfs_funcdesc_t *funcdesc = nfs2_funcdesc;
00739 
00740   nfs_arg_t nfs_arg;
00741   nfs_res_t nfs_res;
00742   struct svc_req req;
00743   int rc;
00744   cmdnfs_thr_info_t *p_thr_info = NULL;
00745 
00746   short exportid;
00747   exportlist_t *pexport;
00748 
00749   if(is_nfs_layer_initialized != TRUE)
00750     {
00751       fprintf(output, "\tNFS layer not initialized.\n");
00752       return -1;
00753     }
00754 
00755   p_thr_info = GetNFSClient();
00756 
00757   if(p_thr_info->is_thread_init != TRUE)
00758     {
00759       if((rc = InitNFSClient(p_thr_info)))
00760         {
00761           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
00762           return -1;
00763         }
00764     }
00765 
00766   while(funcdesc->func_name != NULL)
00767     {
00768       if(!strcmp(funcdesc->func_name, argv[0]))
00769         {
00770 
00771           /* encoding args */
00772 
00773           if(funcdesc->func_encode(CMDNFS_ENCODE,
00774                                    argc - 1, argv + 1,
00775                                    0, NULL, (caddr_t) & nfs_arg) == FALSE)
00776             {
00777               fprintf(output, "%s: bad arguments.\n", argv[0]);
00778               fprintf(output, "Usage: %s\n", funcdesc->func_help);
00779               return -1;
00780             }
00781 
00782           /* preparing request identifier */
00783 
00784           req.rq_prog = NFS_PROGRAM;
00785           req.rq_vers = NFS_V2;
00786           req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
00787 
00788           /* the only function that doesn't take a filehandle */
00789           if(funcdesc->func_call != nfs_Null)
00790             {
00791               exportid = nfs2_FhandleToExportId((fhandle2 *) & nfs_arg);
00792               if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
00793                 {
00794                   /* invalid handle */
00795                   fprintf(output, "\t%s: Bad arguments: Invalid file handle.\n", argv[0]);
00796                   return -1;
00797                 }
00798             }
00799           else
00800             pexport = NULL;
00801 
00802           /* nfs call */
00803 
00804           rc = funcdesc->func_call(&nfs_arg,
00805                                    pexport,
00806                                    &(p_thr_info->context),
00807                                    &(p_thr_info->client), &req, &nfs_res);
00808 
00809           /* freeing args */
00810 
00811           funcdesc->func_encode(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
00812 
00813 #ifdef _DEBUG_NFS_SHELL
00814           printf("NFSv2: RETURNED STRUCTURE:\n");
00815           print_nfs_res(&nfs_res);
00816 #endif
00817 
00818           /* decoding output */
00819 
00820           funcdesc->func_decode(CMDNFS_DECODE, 0, NULL, 0, output, (caddr_t) & nfs_res);
00821 
00822           funcdesc->func_free(&nfs_res);
00823 
00824           /* returning status */
00825           return rc;
00826 
00827         }
00828 
00829       /* pointer to the next cmdnfs_funcdesc_t */
00830       funcdesc++;
00831     }
00832 
00833   fprintf(output, "%s: command not found in NFS2 protocol.\n", argv[0]);
00834   return -1;
00835 
00836 }
00837 
00839 int fn_NFS3_command(int argc,   /* IN : number of args in argv */
00840                     char **argv,        /* IN : arg list               */
00841                     FILE * output       /* IN : output stream          */
00842     )
00843 {
00844 
00845   cmdnfs_funcdesc_t *funcdesc = nfs3_funcdesc;
00846 
00847   nfs_arg_t nfs_arg;
00848   nfs_res_t nfs_res;
00849   struct svc_req req;
00850   int rc;
00851   cmdnfs_thr_info_t *p_thr_info = NULL;
00852 
00853   short exportid;
00854   exportlist_t *pexport;
00855 
00856   if(is_nfs_layer_initialized != TRUE)
00857     {
00858       fprintf(output, "\tNFS layer not initialized.\n");
00859       return -1;
00860     }
00861 
00862   p_thr_info = GetNFSClient();
00863 
00864   if(p_thr_info->is_thread_init != TRUE)
00865     {
00866       if((rc = InitNFSClient(p_thr_info)))
00867         {
00868           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
00869           return -1;
00870         }
00871     }
00872 
00873   while(funcdesc->func_name != NULL)
00874     {
00875       if(!strcmp(funcdesc->func_name, argv[0]))
00876         {
00877 
00878           /* encoding args */
00879 
00880           if(funcdesc->func_encode(CMDNFS_ENCODE,
00881                                    argc - 1, argv + 1,
00882                                    0, NULL, (caddr_t) & nfs_arg) == FALSE)
00883             {
00884               fprintf(output, "%s: bad arguments.\n", argv[0]);
00885               fprintf(output, "Usage: %s\n", funcdesc->func_help);
00886               return -1;
00887             }
00888 
00889           /* preparing request identifier */
00890 
00891           req.rq_prog = NFS_PROGRAM;
00892           req.rq_vers = NFS_V3;
00893           req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
00894 
00895           /* the only function that doesn't take a filehandle */
00896           if(funcdesc->func_call != nfs_Null)
00897             {
00898               exportid = nfs3_FhandleToExportId((nfs_fh3 *) & nfs_arg);
00899               if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
00900                 {
00901                   /* invalid handle */
00902                   fprintf(output, "\t%s: Bad arguments: Invalid file handle.\n", argv[0]);
00903                   return -1;
00904                 }
00905             }
00906           else
00907             pexport = NULL;
00908 
00909           /* nfs call */
00910 
00911           rc = funcdesc->func_call(&nfs_arg,
00912                                    pexport,
00913                                    &(p_thr_info->context),
00914                                    &(p_thr_info->client), &req, &nfs_res);
00915 
00916           /* freeing args */
00917 
00918           funcdesc->func_encode(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
00919 
00920 #ifdef _DEBUG_NFS_SHELL
00921           printf("NFSv3: RETURNED STRUCTURE:\n");
00922           print_nfs_res(&nfs_res);
00923 #endif
00924 
00925           /* decoding output */
00926 
00927           funcdesc->func_decode(CMDNFS_DECODE, 0, NULL, 0, output, (caddr_t) & nfs_res);
00928 
00929           funcdesc->func_free(&nfs_res);
00930 
00931           /* returning status */
00932           return rc;
00933 
00934         }
00935 
00936       /* pointer to the next cmdnfs_funcdesc_t */
00937       funcdesc++;
00938     }
00939 
00940   fprintf(output, "%s: command not found in NFS3 protocol.\n", argv[0]);
00941   return -1;
00942 
00943 }                               /* fn_NFS3_command */
00944 
00945 /*------------------------------------------------------------
00946  *     Wrapping of NFS calls (used by high level commands)
00947  *-----------------------------------------------------------*/
00948 
00949 /* solves a relative or aboslute path */
00950 static int nfs_solvepath(cmdnfs_thr_info_t * p_thr_info, char *io_global_path,  /* global path */
00951                          int size_global_path,  /* max size for global path */
00952                          char *i_spec_path,     /* specified path */
00953                          shell_fh3_t * p_current_hdl,   /* current directory handle */
00954                          shell_fh3_t * pnew_hdl,        /* pointer to solved handle */
00955                          FILE * output)
00956 {
00957   char str_path[NFS2_MAXPATHLEN];
00958   char *pstr_path = str_path;
00959 
00960   char tmp_path[NFS2_MAXPATHLEN];
00961   char *next_name;
00962   char *curr;
00963   int last = 0;
00964   int rc;
00965 
00966   shell_fh3_t hdl_lookup;
00967   nfs_fh3 hdl_param;
00968 
00969   diropargs3 dirop_arg;
00970   LOOKUP3res lookup_res;
00971   struct svc_req req;
00972   short exportid;
00973   exportlist_t *pexport;
00974 
00975   strncpy(str_path, i_spec_path, NFS2_MAXPATHLEN);
00976   curr = str_path;
00977   next_name = str_path;
00978 
00979   if(str_path[0] == '@')
00980     {
00981 
00982       rc = cmdnfs_fhandle3(CMDNFS_ENCODE, 1, &pstr_path, 0, NULL, (caddr_t) & hdl_param);
00983 
00984       if(rc != TRUE)
00985         {
00986           fprintf(output, "Invalid FileHandle: %s\n", str_path);
00987           return -1;
00988         }
00989 
00990       strncpy(io_global_path, str_path, size_global_path);
00991 
00992       set_shell_fh3(pnew_hdl, &hdl_param);
00993 
00994       cmdnfs_fhandle3(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & hdl_param);
00995 
00996       return 0;
00997 
00998     }
00999   else if(str_path[0] == '/')
01000     {
01001       /* absolute path, starting from "/", with a relative path */
01002       curr++;
01003       next_name++;
01004       hdl_lookup = p_thr_info->mounted_path_hdl;
01005       strncpy(tmp_path, "/", NFS2_MAXPATHLEN);
01006 
01007       /* the the directory  is /, return */
01008       if(str_path[1] == '\0')
01009         {
01010           strncpy(io_global_path, tmp_path, size_global_path);
01011           *pnew_hdl = hdl_lookup;
01012           return 0;
01013         }
01014 
01015     }
01016   else
01017     {
01018       hdl_lookup = *p_current_hdl;
01019       strncpy(tmp_path, io_global_path, NFS2_MAXPATHLEN);
01020     }
01021 
01022   /* Now, the path is a relative path, proceed a step by step lookup */
01023   do
01024     {
01025       /* tokenize to the next '/' */
01026       while((curr[0] != '\0') && (curr[0] != '/'))
01027         curr++;
01028 
01029       if(!curr[0])
01030         last = 1;               /* remembers if it was the last dir */
01031 
01032       curr[0] = '\0';
01033 
01034       /* build the arguments */
01035 
01036       set_nfs_fh3(&dirop_arg.dir, &hdl_lookup);
01037       dirop_arg.name = next_name;
01038 
01039       /* preparing request identifier */
01040 
01041       req.rq_prog = NFS_PROGRAM;
01042       req.rq_vers = NFS_V3;
01043       req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01044 
01045       exportid = nfs3_FhandleToExportId(&dirop_arg.dir);
01046       if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01047         {
01048           /* invalid handle */
01049           fprintf(output, "\tBad arguments: Invalid file handle.\n");
01050           return -1;
01051         }
01052 
01053       /* lookup this name */
01054 
01055       rc = nfs_Lookup((nfs_arg_t *) & dirop_arg,
01056                       pexport,
01057                       &(p_thr_info->context),
01058                       &(p_thr_info->client), &req, (nfs_res_t *) & lookup_res);
01059 
01060       if(rc != 0)
01061         {
01062           fprintf(output, "Error %d in nfs_Lookup.\n", rc);
01063           return rc;
01064         }
01065 
01066       rc = lookup_res.status;
01067       if(rc != NFS3_OK)
01068         {
01069           nfs3_Lookup_Free((nfs_res_t *) & lookup_res);
01070           fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01071           return rc;
01072         }
01073 
01074       /* updates current handle */
01075       set_shell_fh3(&hdl_lookup, &lookup_res.LOOKUP3res_u.resok.object);
01076 
01077       nfs3_Lookup_Free((nfs_res_t *) & lookup_res);
01078 
01079       /* adds /name at the end of the path */
01080       strncat(tmp_path, "/", FSAL_MAX_PATH_LEN);
01081       strncat(tmp_path, next_name, FSAL_MAX_PATH_LEN - strlen(tmp_path));
01082 
01083       /* updates cursors */
01084       if(!last)
01085         {
01086           curr++;
01087           next_name = curr;
01088           /* ignore successive slashes */
01089           while((curr[0] != '\0') && (curr[0] == '/'))
01090             {
01091               curr++;
01092               next_name = curr;
01093             }
01094           if(!curr[0])
01095             last = 1;           /* it is the last dir */
01096         }
01097 
01098     }
01099   while(!last);
01100 
01101   /* everything is OK, apply changes */
01102   clean_path(tmp_path, size_global_path);
01103   strncpy(io_global_path, tmp_path, size_global_path);
01104 
01105   *pnew_hdl = hdl_lookup;
01106   return 0;
01107 
01108 }                               /* nfs_solvepath */
01109 
01110 static int nfs_getattr(cmdnfs_thr_info_t * p_thr_info, shell_fh3_t * p_hdl,
01111                        fattr3 * attrs, FILE * output)
01112 {
01113   GETATTR3res res;
01114   struct svc_req req;
01115   unsigned short exportid;
01116   exportlist_t *pexport;
01117   int rc;
01118 
01119   nfs_fh3 nfshdl;
01120 
01121   /* preparing request identifier */
01122 
01123   req.rq_prog = NFS_PROGRAM;
01124   req.rq_vers = NFS_V3;
01125   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01126 
01127   set_nfs_fh3(&nfshdl, p_hdl);
01128 
01129   exportid = nfs3_FhandleToExportId(&nfshdl);
01130   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01131     {
01132       /* invalid handle */
01133       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01134       return -1;
01135     }
01136 
01137   rc = nfs_Getattr((nfs_arg_t *) & nfshdl,
01138                    pexport,
01139                    &(p_thr_info->context),
01140                    &(p_thr_info->client), &req, (nfs_res_t *) & res);
01141 
01142   if(rc != 0)
01143     {
01144       fprintf(output, "Error %d in nfs_Getattr.\n", rc);
01145       return rc;
01146     }
01147 
01148   rc = res.status;
01149   if(rc != NFS3_OK)
01150     {
01151       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01152 
01153       nfs_Getattr_Free((nfs_res_t *) & res);
01154       return rc;
01155     }
01156 
01157   /* updates current handle */
01158   *attrs = res.GETATTR3res_u.resok.obj_attributes;
01159 
01160   nfs_Getattr_Free((nfs_res_t *) & res);
01161 
01162   return 0;
01163 
01164 }
01165 
01166 static int nfs_access(cmdnfs_thr_info_t * p_thr_info, shell_fh3_t * p_hdl, nfs3_uint32 * access_mask,   /* IN/OUT */
01167                       FILE * output)
01168 {
01169   ACCESS3args arg;
01170   ACCESS3res res;
01171   struct svc_req req;
01172   unsigned short exportid;
01173   exportlist_t *pexport;
01174   int rc;
01175 
01176   /* preparing args */
01177   set_nfs_fh3(&arg.object, p_hdl);
01178   arg.access = *access_mask;
01179 
01180   /* preparing request identifier */
01181 
01182   req.rq_prog = NFS_PROGRAM;
01183   req.rq_vers = NFS_V3;
01184   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01185 
01186   exportid = nfs3_FhandleToExportId(&arg.object);
01187   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01188     {
01189       /* invalid handle */
01190       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01191       return -1;
01192     }
01193 
01194   rc = nfs3_Access((nfs_arg_t *) & arg,
01195                    pexport,
01196                    &(p_thr_info->context),
01197                    &(p_thr_info->client), &req, (nfs_res_t *) & res);
01198 
01199   if(rc != 0)
01200     {
01201       fprintf(output, "Error %d in nfs_Access.\n", rc);
01202       return rc;
01203     }
01204 
01205   rc = res.status;
01206   if(rc != NFS3_OK)
01207     {
01208       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01209       nfs3_Access_Free((nfs_res_t *) & res);
01210       return rc;
01211     }
01212 
01213   /* updates access mask */
01214   *access_mask = res.ACCESS3res_u.resok.access;
01215 
01216   nfs3_Access_Free((nfs_res_t *) & res);
01217 
01218   return 0;
01219 
01220 }
01221 
01222 static int nfs_readlink(cmdnfs_thr_info_t * p_thr_info, shell_fh3_t * p_hdl,
01223                         char *linkcontent, FILE * output)
01224 {
01225   READLINK3res res;
01226   struct svc_req req;
01227   unsigned short exportid;
01228   exportlist_t *pexport;
01229   int rc;
01230 
01231   nfs_fh3 nfshdl;
01232 
01233   set_nfs_fh3(&nfshdl, p_hdl);
01234 
01235   /* preparing request identifier */
01236 
01237   req.rq_prog = NFS_PROGRAM;
01238   req.rq_vers = NFS_V3;
01239   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01240 
01241   exportid = nfs3_FhandleToExportId(&nfshdl);
01242   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01243     {
01244       /* invalid handle */
01245       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01246       return -1;
01247     }
01248 
01249   rc = nfs_Readlink((nfs_arg_t *) & nfshdl,
01250                     pexport,
01251                     &(p_thr_info->context),
01252                     &(p_thr_info->client), &req, (nfs_res_t *) & res);
01253 
01254   if(rc != 0)
01255     {
01256       fprintf(output, "Error %d in nfs_Readlink.\n", rc);
01257       return rc;
01258     }
01259 
01260   rc = res.status;
01261   if(rc != NFS3_OK)
01262     {
01263       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01264       nfs3_Readlink_Free((nfs_res_t *) & res);
01265       return rc;
01266     }
01267 
01268   /* copy link content */
01269   strcpy(linkcontent, res.READLINK3res_u.resok.data);
01270 
01271   nfs3_Readlink_Free((nfs_res_t *) & res);
01272 
01273   return 0;
01274 
01275 }                               /* nfs_readlink */
01276 
01277 static int nfs_readdirplus(cmdnfs_thr_info_t * p_thr_info, shell_fh3_t * p_dir_hdl, cookie3 cookie, cookieverf3 * p_cookieverf, /* IN/OUT */
01278                            dirlistplus3 * dirlist,
01279                            nfs_res_t ** to_be_freed, FILE * output)
01280 {
01281   READDIRPLUS3args arg;
01282   READDIRPLUS3res *p_res;
01283   struct svc_req req;
01284   unsigned short exportid;
01285   exportlist_t *pexport;
01286   int rc;
01287 
01288   *to_be_freed = NULL;
01289 
01290   /* args */
01291   set_nfs_fh3(&arg.dir, p_dir_hdl);
01292   arg.cookie = cookie;
01293   memcpy(&arg.cookieverf, p_cookieverf, sizeof(cookieverf3));
01294   arg.dircount = 1024;
01295   arg.maxcount = 4096;
01296 
01297   /* preparing request identifier */
01298 
01299   req.rq_prog = NFS_PROGRAM;
01300   req.rq_vers = NFS_V3;
01301   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01302 
01303   exportid = nfs3_FhandleToExportId(&arg.dir);
01304   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01305     {
01306       /* invalid handle */
01307       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01308       return -1;
01309     }
01310 
01311   p_res = gsh_malloc(sizeof(READDIRPLUS3res));
01312 
01313   rc = nfs3_Readdirplus((nfs_arg_t *) & arg,
01314                         pexport,
01315                         &(p_thr_info->context),
01316                         &(p_thr_info->client), &req, (nfs_res_t *) p_res);
01317 
01318   if(rc != 0)
01319     {
01320       gsh_free(p_res);
01321       fprintf(output, "Error %d in nfs3_Readdirplus.\n", rc);
01322       return rc;
01323     }
01324 
01325   rc = p_res->status;
01326   if(rc != NFS3_OK)
01327     {
01328       nfs3_Readdirplus_Free((nfs_res_t *) p_res);
01329       gsh_free(p_res);
01330       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01331       return rc;
01332     }
01333 
01334   memcpy(p_cookieverf, p_res->READDIRPLUS3res_u.resok.cookieverf, sizeof(cookieverf3));
01335 
01336   *dirlist = p_res->READDIRPLUS3res_u.resok.reply;
01337   *to_be_freed = (nfs_res_t *) p_res;
01338 
01339   return 0;
01340 
01341 }                               /* nfs_readdirplus */
01342 
01343 void nfs_readdirplus_free(nfs_res_t * to_free)
01344 {
01345   if(to_free == NULL)
01346     return;
01347 
01348   nfs3_Readdirplus_Free((nfs_res_t *) to_free);
01349   gsh_free(to_free);
01350 }
01351 
01352 static int nfs_create(cmdnfs_thr_info_t * p_thr_info,
01353                       shell_fh3_t * p_dir_hdl, char *obj_name,
01354                       mode_t posix_mode, shell_fh3_t * p_obj_hdl, FILE * output)
01355 {
01356   CREATE3args arg;
01357   CREATE3res res;
01358   struct svc_req req;
01359   unsigned short exportid;
01360   exportlist_t *pexport;
01361   int rc;
01362 
01363   /* preparing arguments */
01364 
01365   set_nfs_fh3(&arg.where.dir, p_dir_hdl);
01366   arg.where.name = obj_name;
01367   arg.how.mode = GUARDED;
01368 
01369   /* preparing request identifier */
01370 
01371   req.rq_prog = NFS_PROGRAM;
01372   req.rq_vers = NFS_V3;
01373   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01374 
01375   exportid = nfs3_FhandleToExportId(&arg.where.dir);
01376   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01377     {
01378       /* invalid handle */
01379       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01380       return -1;
01381     }
01382 
01383   /* empty sattr3 list */
01384   if(cmdnfs_sattr3(CMDNFS_ENCODE, 0, NULL, 0, NULL,
01385                    (caddr_t) & (arg.how.createhow3_u.obj_attributes)) == FALSE)
01386     {
01387       /* invalid handle */
01388       fprintf(output, "\tError encoding nfs arguments.\n");
01389       return -1;
01390     }
01391 
01392   /* only setting mode */
01393   arg.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
01394   arg.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = posix_mode;
01395 
01396   rc = nfs_Create((nfs_arg_t *) & arg,
01397                   pexport,
01398                   &(p_thr_info->context),
01399                   &(p_thr_info->client), &req, (nfs_res_t *) & res);
01400 
01401   if(rc != 0)
01402     {
01403       fprintf(output, "Error %d in nfs_Create.\n", rc);
01404       return rc;
01405     }
01406 
01407   rc = res.status;
01408   if(rc != NFS3_OK)
01409     {
01410       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01411       nfs_Create_Free((nfs_res_t *) & res);
01412       return rc;
01413     }
01414 
01415   /* object handle */
01416   if(res.CREATE3res_u.resok.obj.handle_follows)
01417     set_shell_fh3(p_obj_hdl, &res.CREATE3res_u.resok.obj.post_op_fh3_u.handle);
01418   else
01419     fprintf(output, "Warning: nfs_Create did not return file handle.\n");
01420 
01421   nfs_Create_Free((nfs_res_t *) & res);
01422 
01423   return 0;
01424 
01425 }
01426 
01427 static int nfs_mkdir(cmdnfs_thr_info_t * p_thr_info,
01428                      shell_fh3_t * p_dir_hdl, char *obj_name,
01429                      mode_t posix_mode, shell_fh3_t * p_obj_hdl, FILE * output)
01430 {
01431   MKDIR3args arg;
01432   MKDIR3res res;
01433   struct svc_req req;
01434   unsigned short exportid;
01435   exportlist_t *pexport;
01436   int rc;
01437 
01438   /* preparing request identifier */
01439 
01440   req.rq_prog = NFS_PROGRAM;
01441   req.rq_vers = NFS_V3;
01442   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01443 
01444   /* preparing arguments */
01445 
01446   set_nfs_fh3(&arg.where.dir, p_dir_hdl);
01447   arg.where.name = obj_name;
01448 
01449   exportid = nfs3_FhandleToExportId(&arg.where.dir);
01450   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01451     {
01452       /* invalid handle */
01453       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01454       return -1;
01455     }
01456 
01457   /* empty sattr3 list */
01458   if(cmdnfs_sattr3(CMDNFS_ENCODE, 0, NULL, 0, NULL,
01459                    (caddr_t) & (arg.attributes)) == FALSE)
01460     {
01461       /* invalid handle */
01462       fprintf(output, "\tError encoding nfs arguments.\n");
01463       return -1;
01464     }
01465 
01466   /* only setting mode */
01467   arg.attributes.mode.set_it = TRUE;
01468   arg.attributes.mode.set_mode3_u.mode = posix_mode;
01469 
01470   rc = nfs_Mkdir((nfs_arg_t *) & arg,
01471                  pexport,
01472                  &(p_thr_info->context),
01473                  &(p_thr_info->client), &req, (nfs_res_t *) & res);
01474 
01475   if(rc != 0)
01476     {
01477       fprintf(output, "Error %d in nfs_Mkdir.\n", rc);
01478       return rc;
01479     }
01480 
01481   rc = res.status;
01482   if(rc != NFS3_OK)
01483     {
01484       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01485       nfs_Mkdir_Free((nfs_res_t *) & res);
01486       return rc;
01487     }
01488 
01489   /* object handle */
01490   if(res.MKDIR3res_u.resok.obj.handle_follows)
01491     set_shell_fh3(p_obj_hdl, &res.MKDIR3res_u.resok.obj.post_op_fh3_u.handle);
01492   else
01493     fprintf(output, "Warning: nfs_Mkdir did not return file handle.\n");
01494 
01495   nfs_Mkdir_Free((nfs_res_t *) & res);
01496 
01497   return 0;
01498 
01499 }                               /*nfs_mkdir */
01500 
01501 static int nfs_rmdir(cmdnfs_thr_info_t * p_thr_info,
01502                      shell_fh3_t * p_dir_hdl, char *obj_name, FILE * output)
01503 {
01504   diropargs3 arg;
01505   RMDIR3res res;
01506   struct svc_req req;
01507   unsigned short exportid;
01508   exportlist_t *pexport;
01509   int rc;
01510 
01511   /* preparing request identifier */
01512 
01513   req.rq_prog = NFS_PROGRAM;
01514   req.rq_vers = NFS_V3;
01515   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01516 
01517   /* preparing arguments */
01518 
01519   set_nfs_fh3(&arg.dir, p_dir_hdl);
01520   arg.name = obj_name;
01521 
01522   /* extract expoort id */
01523   exportid = nfs3_FhandleToExportId(&arg.dir);
01524   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01525     {
01526       /* invalid handle */
01527       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01528       return -1;
01529     }
01530 
01531   rc = nfs_Rmdir((nfs_arg_t *) & arg,
01532                  pexport,
01533                  &(p_thr_info->context),
01534                  &(p_thr_info->client), &req, (nfs_res_t *) & res);
01535 
01536   if(rc != 0)
01537     {
01538       fprintf(output, "Error %d in nfs_Rmdir.\n", rc);
01539       return rc;
01540     }
01541 
01542   rc = res.status;
01543   if(rc != NFS3_OK)
01544     {
01545       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01546       nfs_Rmdir_Free((nfs_res_t *) & res);
01547       return rc;
01548     }
01549 
01550   nfs_Rmdir_Free((nfs_res_t *) & res);
01551   return 0;
01552 
01553 }                               /* nfs_rmdir */
01554 
01555 static int nfs_remove(cmdnfs_thr_info_t * p_thr_info,
01556                       shell_fh3_t * p_dir_hdl, char *obj_name, FILE * output)
01557 {
01558   diropargs3 arg;
01559   REMOVE3res res;
01560   struct svc_req req;
01561   unsigned short exportid;
01562   exportlist_t *pexport;
01563   int rc;
01564 
01565   /* preparing request identifier */
01566 
01567   req.rq_prog = NFS_PROGRAM;
01568   req.rq_vers = NFS_V3;
01569   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01570 
01571   /* preparing arguments */
01572 
01573   set_nfs_fh3(&arg.dir, p_dir_hdl);
01574   arg.name = obj_name;
01575 
01576   /* extract export id */
01577 
01578   exportid = nfs3_FhandleToExportId(&arg.dir);
01579   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01580     {
01581       /* invalid handle */
01582       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01583       return -1;
01584     }
01585 
01586   rc = nfs_Remove((nfs_arg_t *) & arg,
01587                   pexport,
01588                   &(p_thr_info->context),
01589                   &(p_thr_info->client), &req, (nfs_res_t *) & res);
01590 
01591   if(rc != 0)
01592     {
01593       fprintf(output, "Error %d in nfs_Remove.\n", rc);
01594       return rc;
01595     }
01596 
01597   rc = res.status;
01598   if(rc != NFS3_OK)
01599     {
01600       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01601       nfs_Remove_Free((nfs_res_t *) & res);
01602       return rc;
01603     }
01604 
01605   nfs_Remove_Free((nfs_res_t *) & res);
01606   return 0;
01607 
01608 }                               /* nfs_remove */
01609 
01610 static int nfs_setattr(cmdnfs_thr_info_t * p_thr_info,
01611                        shell_fh3_t * p_obj_hdl, sattr3 * p_attributes, FILE * output)
01612 {
01613   SETATTR3args arg;
01614   SETATTR3res res;
01615   struct svc_req req;
01616   unsigned short exportid;
01617   exportlist_t *pexport;
01618   int rc;
01619 
01620   /* preparing request identifier */
01621 
01622   req.rq_prog = NFS_PROGRAM;
01623   req.rq_vers = NFS_V3;
01624   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01625 
01626   /* preparing arguments */
01627 
01628   set_nfs_fh3(&arg.object, p_obj_hdl);
01629   arg.new_attributes = *p_attributes;
01630   arg.guard.check = FALSE;
01631 
01632   /* extract export id */
01633   exportid = nfs3_FhandleToExportId(&arg.object);
01634   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01635     {
01636       /* invalid handle */
01637       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01638       return -1;
01639     }
01640 
01641   rc = nfs_Setattr((nfs_arg_t *) & arg,
01642                    pexport,
01643                    &(p_thr_info->context),
01644                    &(p_thr_info->client), &req, (nfs_res_t *) & res);
01645 
01646   if(rc != 0)
01647     {
01648       fprintf(output, "Error %d in nfs_Setattr.\n", rc);
01649       return rc;
01650     }
01651 
01652   rc = res.status;
01653   if(rc != NFS3_OK)
01654     {
01655       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01656       nfs_Setattr_Free((nfs_res_t *) & res);
01657       return rc;
01658     }
01659 
01660   nfs_Setattr_Free((nfs_res_t *) & res);
01661   return 0;
01662 
01663 }                               /*nfs_setattr */
01664 
01665 static int nfs_rename(cmdnfs_thr_info_t * p_thr_info,
01666                       shell_fh3_t * p_src_dir_hdl, char *src_name,
01667                       shell_fh3_t * p_tgt_dir_hdl, char *tgt_name, FILE * output)
01668 {
01669   RENAME3args arg;
01670   RENAME3res res;
01671   struct svc_req req;
01672   unsigned short exportid;
01673   exportlist_t *pexport;
01674   int rc;
01675 
01676   /* preparing request identifier */
01677 
01678   req.rq_prog = NFS_PROGRAM;
01679   req.rq_vers = NFS_V3;
01680   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01681 
01682   /* preparing arguments */
01683 
01684   set_nfs_fh3(&arg.from.dir, p_src_dir_hdl);
01685   arg.from.name = src_name;
01686   set_nfs_fh3(&arg.to.dir, p_tgt_dir_hdl);
01687   arg.to.name = tgt_name;
01688 
01689   /* extract export id */
01690   exportid = nfs3_FhandleToExportId(&arg.from.dir);
01691   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01692     {
01693       /* invalid handle */
01694       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01695       return -1;
01696     }
01697 
01698   rc = nfs_Rename((nfs_arg_t *) & arg,
01699                   pexport,
01700                   &(p_thr_info->context),
01701                   &(p_thr_info->client), &req, (nfs_res_t *) & res);
01702 
01703   if(rc != 0)
01704     {
01705       fprintf(output, "Error %d in nfs_Rename.\n", rc);
01706       return rc;
01707     }
01708 
01709   rc = res.status;
01710   if(rc != NFS3_OK)
01711     {
01712       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01713       nfs_Rename_Free((nfs_res_t *) & res);
01714       return rc;
01715     }
01716 
01717   nfs_Rename_Free((nfs_res_t *) & res);
01718   return 0;
01719 
01720 }                               /*nfs_rename */
01721 
01722 static int nfs_link(cmdnfs_thr_info_t * p_thr_info,
01723                     shell_fh3_t * p_file_hdl,
01724                     shell_fh3_t * p_tgt_dir_hdl, char *tgt_name, FILE * output)
01725 {
01726   LINK3args arg;
01727   LINK3res res;
01728   struct svc_req req;
01729   unsigned short exportid;
01730   exportlist_t *pexport;
01731   int rc;
01732 
01733   /* preparing request identifier */
01734 
01735   req.rq_prog = NFS_PROGRAM;
01736   req.rq_vers = NFS_V3;
01737   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01738 
01739   /* preparing arguments */
01740 
01741   set_nfs_fh3(&arg.file, p_file_hdl);
01742   set_nfs_fh3(&arg.link.dir, p_tgt_dir_hdl);
01743   arg.link.name = tgt_name;
01744 
01745   /* extract export id */
01746   exportid = nfs3_FhandleToExportId(&arg.file);
01747   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01748     {
01749       /* invalid handle */
01750       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01751       return -1;
01752     }
01753 
01754   rc = nfs_Link((nfs_arg_t *) & arg,
01755                 pexport,
01756                 &(p_thr_info->context),
01757                 &(p_thr_info->client), &req, (nfs_res_t *) & res);
01758 
01759   if(rc != 0)
01760     {
01761       fprintf(output, "Error %d in nfs_Link.\n", rc);
01762       return rc;
01763     }
01764 
01765   rc = res.status;
01766   if(rc != NFS3_OK)
01767     {
01768       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01769       nfs_Link_Free((nfs_res_t *) & res);
01770       return rc;
01771     }
01772 
01773   nfs_Link_Free((nfs_res_t *) & res);
01774   return 0;
01775 
01776 }                               /*nfs_link */
01777 
01778 static int nfs_symlink(cmdnfs_thr_info_t * p_thr_info,
01779                        shell_fh3_t path_hdl, char *link_name,
01780                        char *link_content, sattr3 * p_setattr,
01781                        shell_fh3_t * p_link_hdl, FILE * output)
01782 {
01783   SYMLINK3args arg;
01784   SYMLINK3res res;
01785   struct svc_req req;
01786   unsigned short exportid;
01787   exportlist_t *pexport;
01788   int rc;
01789 
01790   /* preparing request identifier */
01791 
01792   req.rq_prog = NFS_PROGRAM;
01793   req.rq_vers = NFS_V3;
01794   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01795 
01796   /* preparing arguments */
01797 
01798   set_nfs_fh3(&arg.where.dir, &path_hdl);
01799   arg.where.name = link_name;
01800   arg.symlink.symlink_attributes = *p_setattr;
01801   arg.symlink.symlink_data = link_content;
01802 
01803   exportid = nfs3_FhandleToExportId(&arg.where.dir);
01804   if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
01805     {
01806       /* invalid handle */
01807       fprintf(output, "\tBad arguments: Invalid file handle.\n");
01808       return -1;
01809     }
01810 
01811   rc = nfs_Symlink((nfs_arg_t *) & arg,
01812                    pexport,
01813                    &(p_thr_info->context),
01814                    &(p_thr_info->client), &req, (nfs_res_t *) & res);
01815 
01816   if(rc != 0)
01817     {
01818       fprintf(output, "Error %d in nfs_Symlink.\n", rc);
01819       return rc;
01820     }
01821 
01822   rc = res.status;
01823   if(rc != NFS3_OK)
01824     {
01825       fprintf(output, "Error %d in NFSv3 protocol: %s\n", rc, nfsstat3_to_str(rc));
01826       /* free nfs call resources */
01827       nfs_Symlink_Free((nfs_res_t *) & res);
01828       return rc;
01829     }
01830 
01831   /* returned handle */
01832   if(res.SYMLINK3res_u.resok.obj.handle_follows)
01833     {
01834       set_shell_fh3(p_link_hdl, &res.SYMLINK3res_u.resok.obj.post_op_fh3_u.handle);
01835     }
01836   else
01837     {
01838       fprintf(output, "Warning: nfs_Symlink did not return file handle.\n");
01839     }
01840 
01841   /* free nfs call resources */
01842   nfs_Symlink_Free((nfs_res_t *) & res);
01843 
01844   return 0;
01845 
01846 }                               /*nfs_symlink */
01847 
01848 /*------------------------------------------------------------
01849  *          High level, shell-like commands
01850  *-----------------------------------------------------------*/
01851 
01853 int fn_nfs_mount(int argc,      /* IN : number of args in argv */
01854                  char **argv,   /* IN : arg list               */
01855                  FILE * output) /* IN : output stream          */
01856 {
01857   nfs_arg_t nfs_arg;
01858   nfs_res_t nfs_res;
01859   struct svc_req req;
01860   int rc;
01861   char buff[2 * NFS3_FHSIZE + 1];
01862   mountres3 *p_mountres = (mountres3 *) & nfs_res;
01863 
01864   cmdnfs_thr_info_t *p_thr_info = NULL;
01865 
01866   if(is_nfs_layer_initialized != TRUE)
01867     {
01868       fprintf(output, "\tNFS layer not initialized.\n");
01869       return -1;
01870     }
01871 
01872   p_thr_info = GetNFSClient();
01873 
01874   /* We only need to init thread in mount command. */
01875   if(p_thr_info->is_thread_init != TRUE)
01876     {
01877       if((rc = InitNFSClient(p_thr_info)))
01878         {
01879           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
01880           return -1;
01881         }
01882     }
01883 
01884   /* check if a path has already been mounted */
01885 
01886   if(p_thr_info->is_mounted_path != FALSE)
01887     {
01888       fprintf(output, "%s: a path is already mounted. Use \"umount\" command first.\n",
01889               argv[0]);
01890       return -1;
01891     }
01892 
01893   if(cmdnfs_dirpath(CMDNFS_ENCODE,
01894                     argc - 1, argv + 1, 0, NULL, (caddr_t) & nfs_arg) == FALSE)
01895     {
01896       fprintf(output, "%s: bad arguments.\n", argv[0]);
01897       fprintf(output, "Usage: mount <path>.\n");
01898       return -1;
01899     }
01900 
01901   /* preparing request identifier */
01902   req.rq_prog = MOUNTPROG;
01903   req.rq_vers = MOUNT_V3;
01904   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
01905 
01906   /* nfs call */
01907 
01908   rc = mnt_Mnt(&nfs_arg,
01909                pexportlist,
01910                &(p_thr_info->context), &(p_thr_info->client), &req, &nfs_res);
01911 
01912   /* freeing args */
01913 
01914   cmdnfs_dirpath(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
01915 
01916   if(rc != 0)
01917     {
01918       fprintf(output, "%s: Error %d in mnt_Mnt.\n", argv[0], rc);
01919       return rc;
01920     }
01921 
01922   rc = p_mountres->fhs_status;
01923   if(rc != MNT3_OK)
01924     {
01925       mnt3_Mnt_Free(&nfs_res);
01926       fprintf(output, "%s: Error %d in MNT3 protocol.\n", argv[0], rc);
01927       return rc;
01928     }
01929 
01930   set_shell_fh3(&p_thr_info->mounted_path_hdl,
01931                 (nfs_fh3 *) & p_mountres->mountres3_u.mountinfo.fhandle);
01932 
01933   mnt3_Mnt_Free(&nfs_res);
01934 
01935   strcpy(p_thr_info->mounted_path, argv[1]);
01936 
01937   p_thr_info->current_path_hdl = p_thr_info->mounted_path_hdl;
01938   strcpy(p_thr_info->current_path, "/");
01939 
01940   p_thr_info->is_mounted_path = TRUE;
01941 
01942   fprintf(output, "Current directory is \"%s\" \n", p_thr_info->current_path);
01943   snprintmem(buff, 2 * NFS3_FHSIZE + 1,
01944              (caddr_t) p_thr_info->current_path_hdl.data_val,
01945              p_thr_info->current_path_hdl.data_len);
01946   fprintf(output, "Current File handle is \"@%s\" \n", buff);
01947 
01948   return 0;
01949 }
01950 
01952 int fn_nfs_umount(int argc,     /* IN : number of args in argv */
01953                   char **argv,  /* IN : arg list               */
01954                   FILE * output)        /* IN : output stream          */
01955 {
01956   nfs_arg_t nfs_arg;
01957   nfs_res_t nfs_res;
01958   struct svc_req req;
01959   int rc;
01960 
01961   cmdnfs_thr_info_t *p_thr_info = NULL;
01962 
01963   if(is_nfs_layer_initialized != TRUE)
01964     {
01965       fprintf(output, "\tNFS layer not initialized.\n");
01966       return -1;
01967     }
01968 
01969   p_thr_info = GetNFSClient();
01970 
01971   /* We only need to init thread in mount command. */
01972   if(p_thr_info->is_thread_init != TRUE)
01973     {
01974       if((rc = InitNFSClient(p_thr_info)))
01975         {
01976           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
01977           return -1;
01978         }
01979     }
01980 
01981   /* check if a path has already been mounted */
01982 
01983   if(p_thr_info->is_mounted_path != TRUE)
01984     {
01985       fprintf(output, "%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
01986       return -1;
01987     }
01988 
01989   if(cmdnfs_dirpath(CMDNFS_ENCODE,
01990                     argc - 1, argv + 1, 0, NULL, (caddr_t) & nfs_arg) == FALSE)
01991     {
01992       fprintf(output, "%s: bad arguments.\n", argv[0]);
01993       fprintf(output, "Usage: umount <path>.\n");
01994       return -1;
01995     }
01996 
01997   if(strncmp(argv[1], p_thr_info->mounted_path, NFS2_MAXPATHLEN))
01998     {
01999       fprintf(output, "%s: this path is not mounted.\n", argv[0]);
02000       fprintf(output, "Current monted path : %s.\n", p_thr_info->mounted_path);
02001       return -1;
02002     }
02003 
02004   /* preparing request identifier */
02005   req.rq_prog = MOUNTPROG;
02006   req.rq_vers = MOUNT_V3;
02007   req.rq_clntcred = (caddr_t) & p_thr_info->authunix_struct;
02008 
02009   /* nfs call */
02010 
02011   rc = mnt_Umnt(&nfs_arg,
02012                 pexportlist,
02013                 &(p_thr_info->context), &(p_thr_info->client), &req, &nfs_res);
02014 
02015   /* freeing args */
02016 
02017   cmdnfs_dirpath(CMDNFS_FREE, 0, NULL, 0, NULL, (caddr_t) & nfs_arg);
02018 
02019   if(rc != 0)
02020     {
02021       fprintf(output, "%s: Error %d in mnt_Umnt.\n", argv[0], rc);
02022       return rc;
02023     }
02024 
02025   mnt_Umnt_Free(&nfs_res);
02026 
02027   p_thr_info->is_mounted_path = FALSE;
02028 
02029   return 0;
02030 }
02031 
02033 int fn_nfs_pwd(int argc,        /* IN : number of args in argv */
02034                char **argv,     /* IN : arg list               */
02035                FILE * output)   /* IN : output stream          */
02036 {
02037   char buff[2 * NFS3_FHSIZE + 1];
02038   cmdnfs_thr_info_t *p_thr_info = NULL;
02039 
02040   if(is_nfs_layer_initialized != TRUE)
02041     {
02042       fprintf(output, "\tNFS layer not initialized.\n");
02043       return -1;
02044     }
02045 
02046   p_thr_info = GetNFSClient();
02047 
02048   /* check if a path has been mounted */
02049 
02050   if(p_thr_info->is_mounted_path != TRUE)
02051     {
02052       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02053       return -1;
02054     }
02055 
02056   fprintf(output, "Current directory is \"%s\" \n", p_thr_info->current_path);
02057   snprintmem(buff, 2 * NFS3_FHSIZE + 1,
02058              (caddr_t) p_thr_info->current_path_hdl.data_val,
02059              p_thr_info->current_path_hdl.data_len);
02060   fprintf(output, "Current File handle is \"@%s\" \n", buff);
02061 
02062   return 0;
02063 }
02064 
02066 int fn_nfs_ls(int argc,         /* IN : number of args in argv */
02067               char **argv,      /* IN : arg list               */
02068               FILE * output)    /* IN : output stream          */
02069 {
02070 #define NFS_READDIR_SIZE 10
02071 
02072   char linkdata[NFS2_MAXPATHLEN];
02073   char item_path[NFS2_MAXPATHLEN];
02074   char *str_name = ".";
02075   shell_fh3_t handle_tmp;
02076   fattr3 attrs;
02077   cookie3 begin_cookie;
02078   bool_t eod_met;
02079   cookieverf3 cookieverf;
02080   dirlistplus3 dirlist;
02081   entryplus3 *p_entry;
02082 
02083   fattr3 *p_attrs;
02084   shell_fh3_t hdl;
02085   shell_fh3_t *p_hdl = NULL;
02086 
02087   nfs_res_t *to_free = NULL;
02088 
02089   int rc = 0;
02090   char glob_path[NFS2_MAXPATHLEN];
02091 
02092   static char format[] = "hvdlSHz";
02093   const char help_ls[] = "usage: ls [options] [name|path]\n"
02094       "options :\n"
02095       "\t-h print this help\n"
02096       "\t-v verbose mode\n"
02097       "\t-d print directory info instead of listing its content\n"
02098       "\t-l print standard UNIX attributes\n"
02099       "\t-S print all supported attributes\n"
02100       "\t-H print the NFS handle\n" "\t-z silent mode (print nothing)\n";
02101 
02102   int option;
02103   int flag_v = 0;
02104   int flag_h = 0;
02105   int flag_d = 0;
02106   int flag_l = 0;
02107   int flag_S = 0;
02108   int flag_H = 0;
02109   int flag_z = 0;
02110   int err_flag = 0;
02111 
02112   cmdnfs_thr_info_t *p_thr_info = NULL;
02113 
02114   if(is_nfs_layer_initialized != TRUE)
02115     {
02116       fprintf(output, "\tNFS layer not initialized.\n");
02117       return -1;
02118     }
02119 
02120   p_thr_info = GetNFSClient();
02121 
02122   /* check if a path has been mounted */
02123 
02124   if(p_thr_info->is_mounted_path != TRUE)
02125     {
02126       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02127       return -1;
02128     }
02129 
02130   /* analysing options */
02131   getopt_init();
02132 
02133   while((option = Getopt(argc, argv, format)) != -1)
02134     {
02135       switch (option)
02136         {
02137         case 'v':
02138           if(flag_v)
02139             fprintf(output,
02140                     "ls: warning: option 'v' has been specified more than once.\n");
02141           else
02142             flag_v++;
02143           break;
02144 
02145         case 'h':
02146           if(flag_h)
02147             fprintf(output,
02148                     "ls: warning: option 'h' has been specified more than once.\n");
02149           else
02150             flag_h++;
02151           break;
02152 
02153         case 'd':
02154           if(flag_d)
02155             fprintf(output,
02156                     "ls: warning: option 'd' has been specified more than once.\n");
02157           else
02158             flag_d++;
02159           break;
02160 
02161         case 'l':
02162           if(flag_l)
02163             fprintf(output,
02164                     "ls: warning: option 'l' has been specified more than once.\n");
02165           else
02166             flag_l++;
02167           break;
02168 
02169         case 'S':
02170           if(flag_S)
02171             fprintf(output,
02172                     "ls: warning: option 'S' has been specified more than once.\n");
02173           else
02174             flag_S++;
02175           break;
02176 
02177         case 'z':
02178           if(flag_z)
02179             fprintf(output,
02180                     "ls: warning: option 'z' has been specified more than once.\n");
02181           else
02182             flag_z++;
02183           break;
02184 
02185         case 'H':
02186           if(flag_H)
02187             fprintf(output,
02188                     "ls: warning: option 'H' has been specified more than once.\n");
02189           else
02190             flag_H++;
02191           break;
02192 
02193         case '?':
02194           fprintf(output, "ls: unknown option : %c\n", Optopt);
02195           err_flag++;
02196           break;
02197         }
02198     }                           /* while */
02199 
02200   if(flag_l + flag_S + flag_H > 1)
02201     {
02202       fprintf(output, "ls: conflict between options l,S,H\n");
02203       err_flag++;
02204     }
02205 
02206   if(flag_z + flag_v > 1)
02207     {
02208       fprintf(output, "ls: can't use -z and -v at the same time\n");
02209       err_flag++;
02210     }
02211 
02212   if(flag_h)
02213     {
02214       fprintf(output, help_ls);
02215       return 0;
02216     }
02217 
02218   if(err_flag)
02219     {
02220       fprintf(output, help_ls);
02221       return -1;
02222     }
02223 
02224   /* copy current global path */
02225   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
02226 
02227   /* first, retrieve the argument (if any) */
02228   if(Optind == argc - 1)
02229     {
02230       str_name = argv[Optind];
02231 
02232       /* retrieving handle */
02233       if((rc = nfs_solvepath(p_thr_info,
02234                             glob_path,
02235                             NFS2_MAXPATHLEN,
02236                              str_name, &p_thr_info->current_path_hdl, &handle_tmp, output)))
02237         return rc;
02238     }
02239   else
02240     {
02241       str_name = ".";
02242       handle_tmp = p_thr_info->current_path_hdl;
02243     }
02244 
02245   if(flag_v)
02246     fprintf(output, "proceeding ls (using NFS protocol) on \"%s\"\n", glob_path);
02247 
02248   if((rc = nfs_getattr(p_thr_info, &handle_tmp, &attrs, output)))
02249     return rc;
02250 
02251   /*
02252    * if the object is a file or a directoy with the -d option specified,
02253    * we only show its info and exit.
02254    */
02255   if((attrs.type != NF3DIR) || flag_d)
02256     {
02257       if((attrs.type == NF3LNK) && flag_l)
02258         {
02259           if((rc = nfs_readlink(p_thr_info, &handle_tmp, linkdata, output)))
02260             return rc;
02261         }
02262 
02263       if(flag_l)
02264         {
02265           if(!flag_z)
02266             print_nfsitem_line(output, &attrs, str_name, linkdata);
02267         }
02268       else if(flag_S)
02269         {
02270           if(!flag_z)
02271             {
02272               fprintf(output, "%s :\n", str_name);
02273               print_nfs_attributes(&attrs, output);
02274             }
02275         }
02276       else if(flag_H)
02277         {
02278           if(!flag_z)
02279             {
02280               char buff[2 * NFS3_FHSIZE + 1];
02281 
02282               snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) handle_tmp.data_val,
02283                          handle_tmp.data_len);
02284               fprintf(output, "%s (@%s)\n", str_name, buff);
02285             }
02286         }
02287       else                      /* only prints the name */
02288         {
02289           if(!flag_z)
02290             fprintf(output, "%s\n", str_name);
02291         }
02292 
02293       return 0;
02294     }
02295 
02296   /* If this point is reached, then the current element is a directory */
02297 
02298   begin_cookie = 0LL;
02299   eod_met = FALSE;
02300   memset(&cookieverf, 0, sizeof(cookieverf3));
02301 
02302   while(!eod_met)
02303     {
02304 
02305       if(flag_v)
02306         fprintf(output, "-->nfs3_Readdirplus( path=%s, cookie=%llu )\n",
02307                 glob_path, begin_cookie);
02308 
02309       if((rc = nfs_readdirplus(p_thr_info, &handle_tmp, begin_cookie, &cookieverf,       /* IN/OUT */
02310                                &dirlist, &to_free, output)))
02311         return rc;
02312 
02313       p_entry = dirlist.entries;
02314 
02315       while(p_entry)
02316         {
02317           if(!strcmp(str_name, "."))
02318             strncpy(item_path, p_entry->name, NFS2_MAXPATHLEN);
02319           else if(str_name[strlen(str_name) - 1] == '/')
02320             snprintf(item_path, NFS2_MAXPATHLEN, "%s%s", str_name, p_entry->name);
02321           else
02322             snprintf(item_path, NFS2_MAXPATHLEN, "%s/%s", str_name, p_entry->name);
02323 
02324           /* interpreting post-op attributes */
02325 
02326           if(p_entry->name_attributes.attributes_follow)
02327             p_attrs = &p_entry->name_attributes.post_op_attr_u.attributes;
02328           else
02329             p_attrs = NULL;
02330 
02331           /* interpreting post-op handle */
02332 
02333           if(p_entry->name_handle.handle_follows)
02334             {
02335               set_shell_fh3(&hdl, &p_entry->name_handle.post_op_fh3_u.handle);
02336               p_hdl = &hdl;
02337             }
02338           else
02339             p_hdl = NULL;
02340 
02341           if((p_attrs != NULL) && (p_hdl != NULL) && (p_attrs->type == NF3LNK))
02342             {
02343               if((rc = nfs_readlink(p_thr_info, p_hdl, linkdata, output)))
02344                 return rc;
02345             }
02346 
02347           if((p_attrs != NULL) && flag_l)
02348             {
02349               print_nfsitem_line(output, p_attrs, item_path, linkdata);
02350             }
02351           else if((p_attrs != NULL) && flag_S)
02352             {
02353               fprintf(output, "%s :\n", item_path);
02354               if(!flag_z)
02355                 print_nfs_attributes(p_attrs, output);
02356             }
02357           else if((p_hdl != NULL) && flag_H)
02358             {
02359               if(!flag_z)
02360                 {
02361                   char buff[2 * NFS3_FHSIZE + 1];
02362 
02363                   snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) p_hdl->data_val,
02364                              p_hdl->data_len);
02365                   fprintf(output, "%s (@%s)\n", item_path, buff);
02366                 }
02367             }
02368           else
02369             {
02370               if(!flag_z)
02371                 fprintf(output, "%s\n", item_path);
02372             }
02373 
02374           begin_cookie = p_entry->cookie;
02375           p_entry = p_entry->nextentry;
02376         }
02377 
02378       /* Ready for next iteration */
02379       eod_met = dirlist.eof;
02380 
02381     }
02382 
02383   nfs_readdirplus_free(to_free);
02384 
02385   return 0;
02386 }                               /* fn_nfs_ls */
02387 
02389 int fn_nfs_cd(int argc,         /* IN : number of args in argv */
02390               char **argv,      /* IN : arg list               */
02391               FILE * output     /* IN : output stream          */
02392     )
02393 {
02394 
02395   const char help_cd[] = "usage: cd <path>\n";
02396 
02397   char glob_path[NFS2_MAXPATHLEN];
02398   shell_fh3_t new_hdl;
02399   int rc;
02400   fattr3 attrs;
02401   nfs3_uint32 mask;
02402 
02403   cmdnfs_thr_info_t *p_thr_info = NULL;
02404 
02405   if(is_nfs_layer_initialized != TRUE)
02406     {
02407       fprintf(output, "\tNFS layer not initialized.\n");
02408       return -1;
02409     }
02410 
02411   p_thr_info = GetNFSClient();
02412 
02413   /* check if a path has been mounted */
02414 
02415   if(p_thr_info->is_mounted_path != TRUE)
02416     {
02417       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02418       return -1;
02419     }
02420 
02421   /* Exactly one arg expected */
02422   if(argc != 2)
02423     {
02424       fprintf(output, help_cd);
02425       return -1;
02426     }
02427 
02428   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
02429 
02430   if((rc =
02431      nfs_solvepath(p_thr_info, glob_path, NFS2_MAXPATHLEN,
02432                    argv[1], &p_thr_info->current_path_hdl, &new_hdl, output)))
02433     return rc;
02434 
02435   /* verify if the object is a directory */
02436 
02437   if((rc = nfs_getattr(p_thr_info, &new_hdl, &attrs, output)))
02438     return rc;
02439 
02440   if(attrs.type != NF3DIR)
02441     {
02442       fprintf(output, "Error: %s is not a directory\n", glob_path);
02443       return ENOTDIR;
02444     }
02445 
02446   /* verify lookup permission  */
02447   mask = ACCESS3_LOOKUP;
02448   if((rc = nfs_access(p_thr_info, &new_hdl, &mask, output)))
02449     return rc;
02450 
02451   if(!(mask & ACCESS3_LOOKUP))
02452     {
02453       fprintf(output, "Error: %s: permission denied.\n", glob_path);
02454       return EACCES;
02455     }
02456 
02457   /* if so, apply changes */
02458   strncpy(p_thr_info->current_path, glob_path, NFS2_MAXPATHLEN);
02459   p_thr_info->current_path_hdl = new_hdl;
02460 
02461   {
02462     char buff[2 * NFS3_FHSIZE + 1];
02463     fprintf(output, "Current directory is \"%s\" \n", p_thr_info->current_path);
02464     snprintmem(buff, 2 * NFS3_FHSIZE + 1,
02465                (caddr_t) p_thr_info->current_path_hdl.data_val,
02466                p_thr_info->current_path_hdl.data_len);
02467     fprintf(output, "Current File handle is \"@%s\" \n", buff);
02468   }
02469 
02470   return 0;
02471 
02472 }
02473 
02475 int fn_nfs_create(int argc,     /* IN : number of args in argv */
02476                   char **argv,  /* IN : arg list               */
02477                   FILE * output /* IN : output stream          */
02478     )
02479 {
02480   static char format[] = "hv";
02481 
02482   const char help_create[] =
02483       "usage: create [-h][-v] <path> <mode>\n"
02484       "       path: path of the file to be created\n"
02485       "       mode: octal mode for the directory to be created (ex: 644)\n";
02486 
02487   char glob_path[NFS2_MAXPATHLEN];
02488   shell_fh3_t new_hdl;
02489   shell_fh3_t subdir_hdl;
02490   int rc, option;
02491   int flag_v = 0;
02492   int flag_h = 0;
02493   int err_flag = 0;
02494   int mode = 0644;
02495 
02496   char tmp_path[NFS2_MAXPATHLEN];
02497   char *path;
02498   char *file;
02499   char *strmode;
02500 
02501   cmdnfs_thr_info_t *p_thr_info = NULL;
02502 
02503   if(is_nfs_layer_initialized != TRUE)
02504     {
02505       fprintf(output, "\tNFS layer not initialized.\n");
02506       return -1;
02507     }
02508 
02509   p_thr_info = GetNFSClient();
02510 
02511   /* check if a path has been mounted */
02512 
02513   if(p_thr_info->is_mounted_path != TRUE)
02514     {
02515       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02516       return -1;
02517     }
02518 
02519   /* analysing options */
02520   getopt_init();
02521   while((option = Getopt(argc, argv, format)) != -1)
02522     {
02523       switch (option)
02524         {
02525         case 'v':
02526           if(flag_v)
02527             fprintf(output,
02528                     "create: warning: option 'v' has been specified more than once.\n");
02529           else
02530             flag_v++;
02531           break;
02532 
02533         case 'h':
02534           if(flag_h)
02535             fprintf(output,
02536                     "create: warning: option 'h' has been specified more than once.\n");
02537           else
02538             flag_h++;
02539           break;
02540 
02541         case '?':
02542           fprintf(output, "create: unknown option : %c\n", Optopt);
02543           err_flag++;
02544           break;
02545         }
02546     }
02547 
02548   if(flag_h)
02549     {
02550       fprintf(output, help_create);
02551       return 0;
02552     }
02553 
02554   /* Exactly 2 args expected */
02555   if(Optind != (argc - 2))
02556     {
02557       err_flag++;
02558     }
02559   else
02560     {
02561       strncpy(tmp_path, argv[Optind], NFS2_MAXPATHLEN);
02562       split_path(tmp_path, &path, &file);
02563 
02564       strmode = argv[Optind + 1];
02565 
02566       /* converting mode string to posix mode */
02567       mode = atomode(strmode);
02568       if(mode < 0)
02569         err_flag++;
02570     }
02571 
02572   if(err_flag)
02573     {
02574       fprintf(output, help_create);
02575       return -1;
02576     }
02577 
02578   /* copy current path. */
02579   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
02580 
02581   /* retrieves path handle */
02582   if((rc = nfs_solvepath(p_thr_info, glob_path, NFS2_MAXPATHLEN,
02583                          path, &p_thr_info->current_path_hdl, &subdir_hdl, output)))
02584     return rc;
02585 
02586   if((rc = nfs_create(p_thr_info, &subdir_hdl, file, mode, &new_hdl, output)))
02587     return rc;
02588 
02589   if(flag_v)
02590     {
02591       char buff[2 * NFS3_FHSIZE + 1];
02592       snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) new_hdl.data_val, new_hdl.data_len);
02593       fprintf(output, "%s/%s successfully created.\n(handle=@%s)\n", glob_path, file,
02594               buff);
02595     }
02596 
02597   return 0;
02598 
02599 }
02600 
02602 int fn_nfs_mkdir(int argc,      /* IN : number of args in argv */
02603                  char **argv,   /* IN : arg list               */
02604                  FILE * output  /* IN : output stream          */
02605     )
02606 {
02607   static char format[] = "hv";
02608 
02609   const char help_mkdir[] =
02610       "usage: mkdir [-h][-v] <path> <mode>\n"
02611       "       path: path of the directory to be created\n"
02612       "       mode: octal mode for the dir to be created (ex: 755)\n";
02613 
02614   char glob_path[NFS2_MAXPATHLEN];
02615   shell_fh3_t new_hdl;
02616   shell_fh3_t subdir_hdl;
02617   int rc, option;
02618   int flag_v = 0;
02619   int flag_h = 0;
02620   int err_flag = 0;
02621   int mode = 0755;
02622 
02623   char tmp_path[NFS2_MAXPATHLEN];
02624   char *path;
02625   char *file;
02626   char *strmode;
02627 
02628   cmdnfs_thr_info_t *p_thr_info = NULL;
02629 
02630   if(is_nfs_layer_initialized != TRUE)
02631     {
02632       fprintf(output, "\tNFS layer not initialized.\n");
02633       return -1;
02634     }
02635 
02636   p_thr_info = GetNFSClient();
02637 
02638   /* check if a path has been mounted */
02639 
02640   if(p_thr_info->is_mounted_path != TRUE)
02641     {
02642       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02643       return -1;
02644     }
02645 
02646   /* analysing options */
02647   getopt_init();
02648   while((option = Getopt(argc, argv, format)) != -1)
02649     {
02650       switch (option)
02651         {
02652         case 'v':
02653           if(flag_v)
02654             fprintf(output,
02655                     "mkdir: warning: option 'v' has been specified more than once.\n");
02656           else
02657             flag_v++;
02658           break;
02659 
02660         case 'h':
02661           if(flag_h)
02662             fprintf(output,
02663                     "mkdir: warning: option 'h' has been specified more than once.\n");
02664           else
02665             flag_h++;
02666           break;
02667 
02668         case '?':
02669           fprintf(output, "mkdir: unknown option : %c\n", Optopt);
02670           err_flag++;
02671           break;
02672         }
02673     }
02674 
02675   if(flag_h)
02676     {
02677       fprintf(output, help_mkdir);
02678       return 0;
02679     }
02680 
02681   /* Exactly 2 args expected */
02682   if(Optind != (argc - 2))
02683     {
02684       err_flag++;
02685     }
02686   else
02687     {
02688       strncpy(tmp_path, argv[Optind], NFS2_MAXPATHLEN);
02689       split_path(tmp_path, &path, &file);
02690 
02691       strmode = argv[Optind + 1];
02692 
02693       /* converting mode string to posix mode */
02694       mode = atomode(strmode);
02695       if(mode < 0)
02696         err_flag++;
02697     }
02698 
02699   if(err_flag)
02700     {
02701       fprintf(output, help_mkdir);
02702       return -1;
02703     }
02704 
02705   /* copy current path. */
02706   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
02707 
02708   /* retrieves path handle */
02709   if((rc = nfs_solvepath(p_thr_info, glob_path, NFS2_MAXPATHLEN,
02710                          path, &p_thr_info->current_path_hdl, &subdir_hdl, output)))
02711     return rc;
02712 
02713   if((rc = nfs_mkdir(p_thr_info, &subdir_hdl, file, mode, &new_hdl, output)))
02714     return rc;
02715 
02716   if(flag_v)
02717     {
02718       char buff[2 * NFS3_FHSIZE + 1];
02719       snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) new_hdl.data_val, new_hdl.data_len);
02720       fprintf(output, "%s/%s successfully created.\n(handle=@%s)\n", glob_path, file,
02721               buff);
02722     }
02723 
02724   return 0;
02725 
02726 }
02727 
02729 int fn_nfs_unlink(int argc,     /* IN : number of args in argv */
02730                   char **argv,  /* IN : arg list               */
02731                   FILE * output /* IN : output stream          */
02732     )
02733 {
02734   static char format[] = "hv";
02735 
02736   const char help_unlink[] =
02737       "usage: unlink [-h][-v] <path>\n"
02738       "       path: path of the directory to be unlinkd\n";
02739 
02740   char glob_path_parent[NFS2_MAXPATHLEN];
02741   char glob_path_object[NFS2_MAXPATHLEN];
02742   shell_fh3_t subdir_hdl;
02743   shell_fh3_t obj_hdl;
02744   fattr3 attrs;
02745   int rc, option;
02746   int flag_v = 0;
02747   int flag_h = 0;
02748   int err_flag = 0;
02749 
02750   char tmp_path[NFS2_MAXPATHLEN];
02751   char *path;
02752   char *file;
02753 
02754   cmdnfs_thr_info_t *p_thr_info = NULL;
02755 
02756   if(is_nfs_layer_initialized != TRUE)
02757     {
02758       fprintf(output, "\tNFS layer not initialized.\n");
02759       return -1;
02760     }
02761 
02762   p_thr_info = GetNFSClient();
02763 
02764   /* check if a path has been mounted */
02765 
02766   if(p_thr_info->is_mounted_path != TRUE)
02767     {
02768       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02769       return -1;
02770     }
02771 
02772   /* analysing options */
02773   getopt_init();
02774   while((option = Getopt(argc, argv, format)) != -1)
02775     {
02776       switch (option)
02777         {
02778         case 'v':
02779           if(flag_v)
02780             fprintf(output,
02781                     "unlink: warning: option 'v' has been specified more than once.\n");
02782           else
02783             flag_v++;
02784           break;
02785 
02786         case 'h':
02787           if(flag_h)
02788             fprintf(output,
02789                     "unlink: warning: option 'h' has been specified more than once.\n");
02790           else
02791             flag_h++;
02792           break;
02793 
02794         case '?':
02795           fprintf(output, "unlink: unknown option : %c\n", Optopt);
02796           err_flag++;
02797           break;
02798         }
02799     }
02800 
02801   if(flag_h)
02802     {
02803       fprintf(output, help_unlink);
02804       return 0;
02805     }
02806 
02807   /* Exactly 1 args expected */
02808   if(Optind != (argc - 1))
02809     {
02810       err_flag++;
02811     }
02812   else
02813     {
02814       strncpy(tmp_path, argv[Optind], NFS2_MAXPATHLEN);
02815       split_path(tmp_path, &path, &file);
02816     }
02817 
02818   /* copy current path. */
02819   strncpy(glob_path_parent, p_thr_info->current_path, NFS2_MAXPATHLEN);
02820 
02821   /* retrieves parent dir handle */
02822   if((rc = nfs_solvepath(p_thr_info, glob_path_parent, NFS2_MAXPATHLEN,
02823                          path, &p_thr_info->current_path_hdl, &subdir_hdl, output)))
02824     return rc;
02825 
02826   /* copy parent path */
02827   strncpy(glob_path_object, glob_path_parent, NFS2_MAXPATHLEN);
02828 
02829   /* lookup on child object */
02830   if((rc = nfs_solvepath(p_thr_info, glob_path_object, NFS2_MAXPATHLEN,
02831                          file, &subdir_hdl, &obj_hdl, output)))
02832     return rc;
02833 
02834   /* get attributes of child object */
02835   if(flag_v)
02836     fprintf(output, "Getting attributes for %s...\n", glob_path_object);
02837 
02838   if((rc = nfs_getattr(p_thr_info, &obj_hdl, &attrs, output)))
02839     return rc;
02840 
02841   if(attrs.type != NF3DIR)
02842     {
02843       if(flag_v)
02844         fprintf(output, "%s is not a directory: calling nfs3_remove...\n",
02845                 glob_path_object);
02846 
02847       if((rc = nfs_remove(p_thr_info, &subdir_hdl, file, output)))
02848         return rc;
02849     }
02850   else
02851     {
02852       if(flag_v)
02853         fprintf(output, "%s is a directory: calling nfs3_rmdir...\n", glob_path_object);
02854 
02855       if((rc = nfs_rmdir(p_thr_info, &subdir_hdl, file, output)))
02856         return rc;
02857     }
02858 
02859   if(flag_v)
02860     fprintf(output, "%s successfully removed.\n", glob_path_object);
02861 
02862   return 0;
02863 
02864 }
02865 
02867 int fn_nfs_setattr(int argc,    /* IN : number of args in argv */
02868                    char **argv, /* IN : arg list               */
02869                    FILE * output /* IN : output stream          */ )
02870 {
02871 
02872   static char format[] = "hv";
02873 
02874   const char help_setattr[] =
02875       "usage: setattr [-h][-v] <path> <attr>=<value>,<attr>=<value>,...\n"
02876       "       where <attr> can be :\n"
02877       "          mode(octal value),\n"
02878       "          uid, gid, (unsigned 32 bits integer)\n"
02879       "          size, (unsigned  64 bits integer)\n"
02880       "          atime, mtime (format: YYYYMMDDHHMMSS.nnnnnnnnn)\n";
02881 
02882   char glob_path[NFS2_MAXPATHLEN];      /* absolute path of the object */
02883 
02884   shell_fh3_t obj_hdl;          /* handle of the object    */
02885   sattr3 set_attrs;             /* attributes to be setted */
02886   char *attr_string;
02887 
02888   int rc, option;
02889   int flag_v = 0;
02890   int flag_h = 0;
02891   int err_flag = 0;
02892 
02893   char file[NFS2_MAXPATHLEN];   /* the relative path to the object */
02894 
02895   cmdnfs_thr_info_t *p_thr_info = NULL;
02896 
02897   if(is_nfs_layer_initialized != TRUE)
02898     {
02899       fprintf(output, "\tNFS layer not initialized.\n");
02900       return -1;
02901     }
02902 
02903   p_thr_info = GetNFSClient();
02904 
02905   /* check if a path has been mounted */
02906 
02907   if(p_thr_info->is_mounted_path != TRUE)
02908     {
02909       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
02910       return -1;
02911     }
02912 
02913   /* analysing options */
02914   getopt_init();
02915 
02916   while((option = Getopt(argc, argv, format)) != -1)
02917     {
02918       switch (option)
02919         {
02920         case 'v':
02921           if(flag_v)
02922             fprintf(output,
02923                     "setattr: warning: option 'v' has been specified more than once.\n");
02924           else
02925             flag_v++;
02926           break;
02927 
02928         case 'h':
02929           if(flag_h)
02930             fprintf(output,
02931                     "setattr: warning: option 'h' has been specified more than once.\n");
02932           else
02933             flag_h++;
02934           break;
02935 
02936         case '?':
02937           fprintf(output, "setattr: unknown option : %c\n", Optopt);
02938           err_flag++;
02939           break;
02940         }
02941     }
02942 
02943   if(flag_h)
02944     {
02945       /* print usage */
02946       fprintf(output, help_setattr);
02947       return 0;
02948     }
02949 
02950   /* Exactly 2 args expected */
02951 
02952   if(Optind != (argc - 2))
02953     {
02954       err_flag++;
02955     }
02956   else
02957     {
02958       strcpy(file, argv[Optind]);
02959       attr_string = argv[Optind + 1];
02960     }
02961 
02962   if(err_flag)
02963     {
02964       fprintf(output, help_setattr);
02965       return -1;
02966     }
02967 
02968   /* copy current absolute path to a local variable. */
02969   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
02970 
02971   /* retrieve handle to the file whose attributes are to be changed */
02972   if((rc =
02973      nfs_solvepath(p_thr_info, glob_path, NFS2_MAXPATHLEN, file,
02974                    &p_thr_info->current_path_hdl, &obj_hdl, output)))
02975     return rc;
02976 
02977   /* Convert the peer (attr_name,attr_val) to an sattr3 structure. */
02978   if(cmdnfs_sattr3(CMDNFS_ENCODE,
02979                    1, &attr_string, 0, NULL, (caddr_t) & set_attrs) == FALSE)
02980     {
02981       fprintf(output, "Invalid nfs arguments.\n");
02982       fprintf(output, help_setattr);
02983       return -1;
02984     }
02985 
02986   /* executes set attrs */
02987   if((rc = nfs_setattr(p_thr_info, &obj_hdl, &set_attrs, output)))
02988     return rc;
02989 
02990   if(flag_v)
02991     fprintf(output, "Attributes of \"%s\" successfully changed.\n", glob_path);
02992 
02993   return 0;
02994 }                               /* fn_nfs_setattr */
02995 
02997 int fn_nfs_rename(int argc,     /* IN : number of args in argv */
02998                   char **argv,  /* IN : arg list               */
02999                   FILE * output /* IN : output stream          */
03000     )
03001 {
03002 
03003   static char format[] = "hv";
03004 
03005   const char help_rename[] = "usage: rename [-h][-v] <src> <dest>\n";
03006 
03007   char src_glob_path[NFS2_MAXPATHLEN];
03008   char tgt_glob_path[NFS2_MAXPATHLEN];
03009 
03010   shell_fh3_t src_path_handle, tgt_path_handle;
03011 
03012   int rc, option;
03013   int flag_v = 0;
03014   int flag_h = 0;
03015   int err_flag = 0;
03016 
03017   char tmp_path1[NFS2_MAXPATHLEN];
03018   char tmp_path2[NFS2_MAXPATHLEN];
03019   char *src_path;
03020   char *src_file;
03021   char *tgt_path;
03022   char *tgt_file;
03023 
03024   cmdnfs_thr_info_t *p_thr_info = NULL;
03025 
03026   if(is_nfs_layer_initialized != TRUE)
03027     {
03028       fprintf(output, "\tNFS layer not initialized.\n");
03029       return -1;
03030     }
03031 
03032   p_thr_info = GetNFSClient();
03033 
03034   /* check if a path has been mounted */
03035 
03036   if(p_thr_info->is_mounted_path != TRUE)
03037     {
03038       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
03039       return -1;
03040     }
03041 
03042   /* analysing options */
03043   getopt_init();
03044   while((option = Getopt(argc, argv, format)) != -1)
03045     {
03046       switch (option)
03047         {
03048         case 'v':
03049           if(flag_v)
03050             fprintf(output,
03051                     "rename: warning: option 'v' has been specified more than once.\n");
03052           else
03053             flag_v++;
03054           break;
03055         case 'h':
03056           if(flag_h)
03057             fprintf(output,
03058                     "rename: warning: option 'h' has been specified more than once.\n");
03059           else
03060             flag_h++;
03061           break;
03062         case '?':
03063           fprintf(output, "rename: unknown option : %c\n", Optopt);
03064           err_flag++;
03065           break;
03066         }
03067     }
03068 
03069   if(flag_h)
03070     {
03071       fprintf(output, help_rename);
03072       return 0;
03073     }
03074 
03075   /* Exactly 2 args expected */
03076   if(Optind != (argc - 2))
03077     {
03078       err_flag++;
03079     }
03080   else
03081     {
03082 
03083       strncpy(tmp_path1, argv[Optind], NFS2_MAXPATHLEN);
03084       split_path(tmp_path1, &src_path, &src_file);
03085 
03086       strncpy(tmp_path2, argv[Optind + 1], NFS2_MAXPATHLEN);
03087       split_path(tmp_path2, &tgt_path, &tgt_file);
03088 
03089     }
03090 
03091   if(err_flag)
03092     {
03093       fprintf(output, help_rename);
03094       return -1;
03095     }
03096 
03097   if(flag_v)
03098     fprintf(output, "Renaming %s (dir %s) to %s (dir %s)\n",
03099             src_file, src_path, tgt_file, tgt_path);
03100 
03101   /* copy current path. */
03102   strncpy(src_glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
03103   strncpy(tgt_glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
03104 
03105   /* retrieves paths handles */
03106   if((rc =
03107      nfs_solvepath(p_thr_info, src_glob_path, NFS2_MAXPATHLEN,
03108                    src_path, &p_thr_info->current_path_hdl, &src_path_handle, output)))
03109     return rc;
03110 
03111   if((rc =
03112      nfs_solvepath(p_thr_info, tgt_glob_path, NFS2_MAXPATHLEN,
03113                    tgt_path, &p_thr_info->current_path_hdl, &tgt_path_handle, output)))
03114     return rc;
03115 
03116   /* Rename operation */
03117 
03118   if((rc = nfs_rename(p_thr_info, &src_path_handle,      /* IN */
03119                      src_file,  /* IN */
03120                      &tgt_path_handle,  /* IN */
03121                      tgt_file,  /* IN */
03122                       output)))
03123     return rc;
03124 
03125   if(flag_v)
03126     fprintf(output, "%s/%s successfully renamed to %s/%s\n",
03127             src_glob_path, src_file, tgt_glob_path, tgt_file);
03128 
03129   return 0;
03130 
03131 }
03132 
03134 int fn_nfs_hardlink(int argc,   /* IN : number of args in argv */
03135                     char **argv,        /* IN : arg list               */
03136                     FILE * output       /* IN : output stream          */
03137     )
03138 {
03139 
03140   static char format[] = "hv";
03141 
03142   const char help_hardlink[] =
03143       "hardlink: create a hard link.\n"
03144       "usage: hardlink [-h][-v] <target> <new_path>\n"
03145       "       target: path of an existing file.\n"
03146       "       new_path: path of the hardlink to be created\n";
03147 
03148   char glob_path_target[NFS2_MAXPATHLEN];
03149   char glob_path_link[NFS2_MAXPATHLEN];
03150 
03151   shell_fh3_t target_hdl, dir_hdl;
03152 
03153   int rc, option;
03154   int flag_v = 0;
03155   int flag_h = 0;
03156   int err_flag = 0;
03157 
03158   char *target = NULL;
03159 
03160   char tmp_path[NFS2_MAXPATHLEN];
03161   char *path;
03162   char *name;
03163 
03164   cmdnfs_thr_info_t *p_thr_info = NULL;
03165 
03166   if(is_nfs_layer_initialized != TRUE)
03167     {
03168       fprintf(output, "\tNFS layer not initialized.\n");
03169       return -1;
03170     }
03171 
03172   p_thr_info = GetNFSClient();
03173 
03174   /* check if a path has been mounted */
03175 
03176   if(p_thr_info->is_mounted_path != TRUE)
03177     {
03178       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
03179       return -1;
03180     }
03181 
03182   /* analysing options */
03183   getopt_init();
03184   while((option = Getopt(argc, argv, format)) != -1)
03185     {
03186       switch (option)
03187         {
03188         case 'v':
03189           if(flag_v)
03190             fprintf(output,
03191                     "hardlink: warning: option 'v' has been specified more than once.\n");
03192           else
03193             flag_v++;
03194           break;
03195         case 'h':
03196           if(flag_h)
03197             fprintf(output,
03198                     "hardlink: warning: option 'h' has been specified more than once.\n");
03199           else
03200             flag_h++;
03201           break;
03202         case '?':
03203           fprintf(output, "hardlink: unknown option : %c\n", Optopt);
03204           err_flag++;
03205           break;
03206         }
03207     }
03208 
03209   if(flag_h)
03210     {
03211       fprintf(output, help_hardlink);
03212       return 0;
03213     }
03214 
03215   /* 2 args expected */
03216 
03217   if(Optind == (argc - 2))
03218     {
03219 
03220       target = argv[Optind];
03221 
03222       strncpy(tmp_path, argv[Optind + 1], NFS2_MAXPATHLEN);
03223       split_path(tmp_path, &path, &name);
03224 
03225     }
03226   else
03227     {
03228       err_flag++;
03229     }
03230 
03231   if(err_flag)
03232     {
03233       fprintf(output, help_hardlink);
03234       return -1;
03235     }
03236 
03237   /* copy current path. */
03238   strncpy(glob_path_target, p_thr_info->current_path, NFS2_MAXPATHLEN);
03239   strncpy(glob_path_link, p_thr_info->current_path, NFS2_MAXPATHLEN);
03240 
03241   /* retrieves path handle for target */
03242   if((rc =
03243      nfs_solvepath(p_thr_info, glob_path_target, NFS2_MAXPATHLEN,
03244                    target, &p_thr_info->current_path_hdl, &target_hdl, output)))
03245     return rc;
03246 
03247   /* retrieves path handle for parent dir */
03248   if((rc =
03249      nfs_solvepath(p_thr_info, glob_path_link, NFS2_MAXPATHLEN,
03250                    path, &p_thr_info->current_path_hdl, &dir_hdl, output)))
03251     return rc;
03252 
03253   rc = nfs_link(p_thr_info, &target_hdl,        /* IN - target file */
03254                 &dir_hdl,       /* IN - parent dir handle */
03255                 name,           /* IN - link name */
03256                 output);        /* OUT - new attributes */
03257 
03258   if(rc)
03259     return rc;
03260 
03261   if(flag_v)
03262     fprintf(output, "%s/%s <=> %s successfully created\n", path, name, glob_path_target);
03263 
03264   return 0;
03265 
03266 }
03267 
03270 int fn_nfs_ln(int argc,         /* IN : number of args in argv */
03271               char **argv,      /* IN : arg list               */
03272               FILE * output     /* IN : output stream          */
03273     )
03274 {
03275 
03276   static char format[] = "hv";
03277 
03278   const char help_ln[] =
03279       "ln: create a symbolic link.\n"
03280       "usage: ln [-h][-v] <link_content> <link_path>\n"
03281       "       link_content: content of the symbolic link to be created\n"
03282       "       link_path: path of the symbolic link to be created\n";
03283 
03284   char glob_path[NFS2_MAXPATHLEN];
03285   shell_fh3_t path_hdl, link_hdl;
03286   sattr3 set_attrs;
03287   int rc, option;
03288   int flag_v = 0;
03289   int flag_h = 0;
03290   int err_flag = 0;
03291 
03292   char *content = NULL;
03293   char tmp_path[NFS2_MAXPATHLEN];
03294   char *path;
03295   char *name;
03296 
03297   cmdnfs_thr_info_t *p_thr_info = NULL;
03298 
03299   if(is_nfs_layer_initialized != TRUE)
03300     {
03301       fprintf(output, "\tNFS layer not initialized.\n");
03302       return -1;
03303     }
03304 
03305   p_thr_info = GetNFSClient();
03306 
03307   /* check if a path has been mounted */
03308 
03309   if(p_thr_info->is_mounted_path != TRUE)
03310     {
03311       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
03312       return -1;
03313     }
03314 
03315   /* analysing options */
03316   getopt_init();
03317   while((option = Getopt(argc, argv, format)) != -1)
03318     {
03319       switch (option)
03320         {
03321         case 'v':
03322           if(flag_v)
03323             fprintf(output,
03324                     "ln: warning: option 'v' has been specified more than once.\n");
03325           else
03326             flag_v++;
03327           break;
03328         case 'h':
03329           if(flag_h)
03330             fprintf(output,
03331                     "ln: warning: option 'h' has been specified more than once.\n");
03332           else
03333             flag_h++;
03334           break;
03335         case '?':
03336           fprintf(output, "ln: unknown option : %c\n", Optopt);
03337           err_flag++;
03338           break;
03339         }
03340     }
03341 
03342   if(flag_h)
03343     {
03344       fprintf(output, help_ln);
03345       return 0;
03346     }
03347 
03348   /* 2 args expected */
03349 
03350   if(Optind == (argc - 2))
03351     {
03352 
03353       content = argv[Optind];
03354 
03355       strncpy(tmp_path, argv[Optind + 1], NFS2_MAXPATHLEN);
03356       split_path(tmp_path, &path, &name);
03357 
03358     }
03359   else
03360     {
03361       err_flag++;
03362     }
03363 
03364   if(err_flag)
03365     {
03366       fprintf(output, help_ln);
03367       return -1;
03368     }
03369 
03370   /* copy current path. */
03371   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
03372 
03373   /* retrieves path handle */
03374   if((rc =
03375      nfs_solvepath(p_thr_info, glob_path, NFS2_MAXPATHLEN,
03376                    path, &p_thr_info->current_path_hdl, &path_hdl, output)))
03377     return rc;
03378 
03379   /* Prepare link attributes : empty sattr3 list */
03380 
03381   if(cmdnfs_sattr3(CMDNFS_ENCODE, 0, NULL, 0, NULL, (caddr_t) & set_attrs) == FALSE)
03382     {
03383       /* invalid handle */
03384       fprintf(output, "\tError encoding nfs arguments.\n");
03385       return -1;
03386     }
03387 
03388   rc = nfs_symlink(p_thr_info, path_hdl,        /* IN - parent dir handle */
03389                    name,        /* IN - link name */
03390                    content,     /* IN - link content */
03391                    &set_attrs,  /* Link attributes */
03392                    &link_hdl,   /* OUT - link handle */
03393                    output);
03394 
03395   if(rc)
03396     return rc;
03397 
03398   if(flag_v)
03399     {
03400       char buff[2 * NFS3_FHSIZE + 1];
03401       snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) link_hdl.data_val,
03402                  link_hdl.data_len);
03403 
03404       fprintf(output, "%s/%s -> %s successfully created (@%s) \n", path, name, content,
03405               buff);
03406     }
03407 
03408   return 0;
03409 }
03410 
03412 int fn_nfs_stat(int argc,       /* IN : number of args in argv */
03413                 char **argv,    /* IN : arg list               */
03414                 FILE * output)  /* IN : output stream          */
03415 {
03416 
03417   shell_fh3_t handle_tmp;
03418   fattr3 attrs;
03419 
03420   int rc = 0;
03421   char glob_path[NFS2_MAXPATHLEN];
03422 
03423   static char format[] = "hvHz";
03424   const char help_stat[] = "usage: stat [options] <path>\n"
03425       "options :\n"
03426       "\t-h print this help\n"
03427       "\t-v verbose mode\n"
03428       "\t-H print the NFS handle\n" "\t-z silent mode (print nothing)\n";
03429 
03430   int option;
03431   char *str_name = NULL;
03432   int flag_v = 0;
03433   int flag_h = 0;
03434   int flag_H = 0;
03435   int flag_z = 0;
03436   int err_flag = 0;
03437 
03438   cmdnfs_thr_info_t *p_thr_info = NULL;
03439 
03440   if(is_nfs_layer_initialized != TRUE)
03441     {
03442       fprintf(output, "\tNFS layer not initialized.\n");
03443       return -1;
03444     }
03445 
03446   p_thr_info = GetNFSClient();
03447 
03448   /* check if a path has been mounted */
03449 
03450   if(p_thr_info->is_mounted_path != TRUE)
03451     {
03452       fprintf(output, "\t%s: no mounted path. Use \"mount\" command first.\n", argv[0]);
03453       return -1;
03454     }
03455 
03456   /* analysing options */
03457   getopt_init();
03458 
03459   while((option = Getopt(argc, argv, format)) != -1)
03460     {
03461       switch (option)
03462         {
03463         case 'v':
03464           if(flag_v)
03465             fprintf(output,
03466                     "stat: warning: option 'v' has been specified more than once.\n");
03467           else
03468             flag_v++;
03469           break;
03470 
03471         case 'h':
03472           if(flag_h)
03473             fprintf(output,
03474                     "stat: warning: option 'h' has been specified more than once.\n");
03475           else
03476             flag_h++;
03477           break;
03478 
03479         case 'z':
03480           if(flag_z)
03481             fprintf(output,
03482                     "stat: warning: option 'z' has been specified more than once.\n");
03483           else
03484             flag_z++;
03485           break;
03486 
03487         case 'H':
03488           if(flag_H)
03489             fprintf(output,
03490                     "stat: warning: option 'H' has been specified more than once.\n");
03491           else
03492             flag_H++;
03493           break;
03494 
03495         case '?':
03496           fprintf(output, "stat: unknown option : %c\n", Optopt);
03497           err_flag++;
03498           break;
03499         }
03500     }                           /* while */
03501 
03502   if(flag_z + flag_v > 1)
03503     {
03504       fprintf(output, "stat: can't use -z and -v at the same time\n");
03505       err_flag++;
03506     }
03507 
03508   if(flag_h)
03509     {
03510       fprintf(output, help_stat);
03511       return 0;
03512     }
03513 
03514   if(Optind != argc - 1)
03515     {
03516       fprintf(output, "stat: Missing argument: <path>\n");
03517       err_flag++;
03518     }
03519   else
03520     {
03521       str_name = argv[Optind];
03522     }
03523 
03524   if(err_flag)
03525     {
03526       fprintf(output, help_stat);
03527       return -1;
03528     }
03529 
03530   /* copy current global path */
03531   strncpy(glob_path, p_thr_info->current_path, NFS2_MAXPATHLEN);
03532 
03533   /* retrieving handle */
03534   if((rc = nfs_solvepath(p_thr_info,
03535                         glob_path,
03536                         NFS2_MAXPATHLEN,
03537                          str_name, &p_thr_info->current_path_hdl, &handle_tmp, output)))
03538     return rc;
03539 
03540   if(flag_v)
03541     fprintf(output, "proceeding stat (using NFS protocol) on \"%s\"\n", glob_path);
03542 
03543   if((rc = nfs_getattr(p_thr_info, &handle_tmp, &attrs, output)))
03544     return rc;
03545 
03546   if(flag_H)
03547     {
03548       if(!flag_z)
03549         {
03550           char buff[2 * NFS3_FHSIZE + 1];
03551 
03552           snprintmem(buff, 2 * NFS3_FHSIZE + 1, (caddr_t) handle_tmp.data_val,
03553                      handle_tmp.data_len);
03554           fprintf(output, "%s (@%s)\n", str_name, buff);
03555         }
03556     }
03557   else if(!flag_z)
03558     {
03559       /*fprintf(output,"%s :\n",str_name); */
03560       print_nfs_attributes(&attrs, output);
03561     }
03562 
03563   return 0;
03564 }                               /* fn_nfs_stat */
03565 
03567 int fn_nfs_su(int argc,         /* IN : number of args in argv */
03568               char **argv,      /* IN : arg list               */
03569               FILE * output)    /* IN : output stream          */
03570 {
03571   int rc, i;
03572   char *str_uid;
03573   uid_t uid;
03574   fsal_status_t st;
03575   struct passwd *pw_struct;
03576 
03577 #define MAX_GRPS  128
03578   gid_t groups_tab[MAX_GRPS];
03579   int nb_grp;
03580 
03581   const char help_su[] = "usage: su <uid>\n";
03582 
03583   cmdnfs_thr_info_t *p_thr_info = NULL;
03584 
03585   if(is_nfs_layer_initialized != TRUE)
03586     {
03587       fprintf(output, "\tNFS layer not initialized.\n");
03588       return -1;
03589     }
03590 
03591   /* UID arg expected */
03592   if(argc != 2)
03593     {
03594       fprintf(output, help_su);
03595       return -1;
03596     }
03597   else
03598     {
03599       str_uid = argv[1];
03600     }
03601 
03602   p_thr_info = GetNFSClient();
03603 
03604   if(p_thr_info->is_thread_init != TRUE)
03605     {
03606       if((rc = InitNFSClient(p_thr_info)))
03607         {
03608           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
03609           return -1;
03610         }
03611     }
03612 
03613   if(isdigit(str_uid[0]))
03614     {
03615       if((uid = my_atoi(str_uid)) == (uid_t) - 1)
03616         {
03617           fprintf(output, "Error: invalid uid \"%s\"\n", str_uid);
03618           return -1;
03619         }
03620       pw_struct = getpwuid(uid);
03621     }
03622   else
03623     {
03624       pw_struct = getpwnam(str_uid);
03625     }
03626 
03627   if(pw_struct == NULL)
03628     {
03629       fprintf(output, "Unknown user %s\n", str_uid);
03630       return errno;
03631     }
03632 
03633   nb_grp = getugroups(MAX_GRPS, groups_tab, pw_struct->pw_name, pw_struct->pw_gid);
03634 
03635   fprintf(output, "Changing user to : %s ( uid = %d, gid = %d )\n",
03636           pw_struct->pw_name, pw_struct->pw_uid, pw_struct->pw_gid);
03637 
03638   if(nb_grp > 1)
03639     {
03640       fprintf(output, "altgroups = ");
03641       for(i = 1; i < nb_grp; i++)
03642         {
03643           if(i == 1)
03644             fprintf(output, "%d", groups_tab[i]);
03645           else
03646             fprintf(output, ", %d", groups_tab[i]);
03647         }
03648       fprintf(output, "\n");
03649     }
03650 
03651   st = FSAL_GetClientContext(&p_thr_info->context, &p_thr_info->exp_context,
03652                              pw_struct->pw_uid, pw_struct->pw_gid, groups_tab, nb_grp);
03653 
03654   if(FSAL_IS_ERROR(st))
03655     {
03656       fprintf(output, "Error executing FSAL_GetUserCred:");
03657       print_fsal_status(output, st);
03658       fprintf(output, "\n");
03659       return st.major;
03660     }
03661 
03662   fprintf(output, "Done.\n");
03663 
03664   return 0;
03665 
03666 }
03667 
03668 int fn_nfs_id(int argc,         /* IN : number of args in argv */
03669               char **argv,      /* IN : arg list               */
03670               FILE * output)    /* IN : output stream          */
03671 {
03672   int rc;
03673   cmdnfs_thr_info_t *p_thr_info = NULL;
03674 
03675   if(is_nfs_layer_initialized != TRUE)
03676     {
03677       fprintf(output, "\tNFS layer not initialized.\n");
03678       return -1;
03679     }
03680 
03681   p_thr_info = GetNFSClient();
03682 
03683   if(p_thr_info->is_thread_init != TRUE)
03684     {
03685       if((rc = InitNFSClient(p_thr_info)))
03686         {
03687           fprintf(output, "\t%s: Error %d during thread initialization.\n", argv[0], rc);
03688           return -1;
03689         }
03690     }
03691 #ifdef _USE_POSIX
03692   {
03693     posixfsal_op_context_t * p_cred
03694       = (posixfsal_op_context_t *)&p_thr_info->context;
03695     fprintf(output, "Current user : uid = %d, gid = %d\n",
03696           p_cred->credential.user, p_cred->credential.group);
03697   }
03698 #endif
03699 
03700   return 0;
03701 }