nfs-ganesha 1.4

commands_FSAL.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00217 #ifdef HAVE_CONFIG_H
00218 #include "config.h"
00219 #endif
00220 
00221 #include <strings.h>
00222 #include <errno.h>
00223 #include <sys/types.h>
00224 #include <sys/stat.h>
00225 #include <sys/time.h>
00226 #include <unistd.h>
00227 #include <time.h>
00228 #include <ctype.h>
00229 #include <string.h>
00230 #include <pwd.h>
00231 #include "fsal.h"
00232 #include "log.h"
00233 #include "err_ghost_fs.h"
00234 #include "config_parsing.h"
00235 #include "cmd_tools.h"
00236 #include "commands.h"
00237 #include "Getopt.h"
00238 #include "abstract_mem.h"
00239 
00240 int nfs_get_fsalpathlib_conf(char *configPath, char *PathLib);
00241 
00242 /* global FS configuration variables */
00243 
00244 #ifdef OLD_LOGGING
00245 static desc_log_stream_t voie;
00246 static log_t log_desc = LOG_INITIALIZER;
00247 #endif
00248 
00249 static int is_loaded = FALSE;   /* filsystem initialization status */
00250 
00251 /* thread specific configuration variables */
00252 
00253 typedef struct cmdfsal_thr_info__
00254 {
00255   int is_thread_ok;             /* per thread initialization status */
00256   fsal_handle_t current_dir;    /* current directory handle */
00257   char current_path[FSAL_MAX_PATH_LEN]; /* current path */
00258 
00259   /* thread's context */
00260   fsal_op_context_t context;
00261 
00262   /* export context : on for each thread,
00263    * on order to make it possible for them
00264    * to access different filesets.
00265    */
00266   fsal_export_context_t exp_context;
00267   int opened;                   /* is file opened ? */
00268   fsal_file_t current_fd;       /* current file descriptor */
00269 
00270 } cmdfsal_thr_info_t;
00271 
00272 /* pthread key to manage thread specific configuration */
00273 
00274 static pthread_key_t thread_key;
00275 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00276 
00277 /* init pthtread_key for current thread */
00278 
00279 static void init_keys(void)
00280 {
00281   if(pthread_key_create(&thread_key, NULL) == -1)
00282     printf("Error %d creating pthread key for thread %p : %s\n",
00283            errno, (caddr_t) pthread_self(), strerror(errno));
00284 
00285   return;
00286 }                               /* init_keys */
00287 
00292 cmdfsal_thr_info_t *GetFSALCmdContext()
00293 {
00294 
00295   cmdfsal_thr_info_t *p_current_thread_vars;
00296 
00297   /* first, we init the keys if this is the first time */
00298   if(pthread_once(&once_key, init_keys) != 0)
00299     {
00300       printf("Error %d calling pthread_once for thread %p : %s\n",
00301              errno, (caddr_t) pthread_self(), strerror(errno));
00302       return NULL;
00303     }
00304 
00305   p_current_thread_vars = (cmdfsal_thr_info_t *) pthread_getspecific(thread_key);
00306 
00307   /* we allocate the thread context if this is the first time */
00308   if(p_current_thread_vars == NULL)
00309     {
00310 
00311       /* allocates thread structure */
00312       p_current_thread_vars = gsh_malloc(sizeof(cmdfsal_thr_info_t));
00313 
00314       /* panic !!! */
00315       if(p_current_thread_vars == NULL)
00316         {
00317           printf("%p:commands_FSAL: Not enough memory\n", (caddr_t) pthread_self());
00318           return NULL;
00319         }
00320 
00321       /* Clean thread context */
00322 
00323       memset(p_current_thread_vars, 0, sizeof(cmdfsal_thr_info_t));
00324 
00325       p_current_thread_vars->is_thread_ok = FALSE;
00326       strcpy(p_current_thread_vars->current_path, "");
00327       p_current_thread_vars->opened = FALSE;
00328 
00329       /* set the specific value */
00330       pthread_setspecific(thread_key, (void *)p_current_thread_vars);
00331 
00332     }
00333 
00334   return p_current_thread_vars;
00335 
00336 }                               /* GetFSALCmdContext */
00337 
00341 int Init_Thread_Context(FILE * output, cmdfsal_thr_info_t * context, int flag_v)
00342 {
00343 
00344   uid_t uid;
00345   char fsal_status_buf[256];
00346   fsal_status_t st;
00347   fsal_handle_t hdl_dir;
00348   char buff[2 * sizeof(fsal_handle_t) + 1];
00349   struct passwd *pw_struct;
00350 
00351   /* for the moment, create export context for root fileset */
00352 #if defined( _USE_XFS )
00353   fsal_path_t local_path_fsal;
00354   st = FSAL_str2path("/xfs", strlen("/xfs"), &local_path_fsal);
00355   st = FSAL_BuildExportContext(&context->exp_context, &local_path_fsal, NULL);
00356 #elif defined( _USE_VFS )
00357   fsal_path_t local_path_fsal;
00358   st = FSAL_str2path("/tmp", strlen("/tmp"), &local_path_fsal);
00359   st = FSAL_BuildExportContext(&context->exp_context, &local_path_fsal, NULL);
00360 #elif defined( _USE_LUSTRE )
00361   fsal_path_t local_path_fsal;
00362   st = FSAL_str2path("/mnt/lustre", strlen("/mnt/lustre"), &local_path_fsal);
00363   st = FSAL_BuildExportContext(&context->exp_context, &local_path_fsal, NULL);
00364 #else
00365   st = FSAL_BuildExportContext(&context->exp_context, NULL, NULL);
00366 #endif
00367 
00368   if(FSAL_IS_ERROR(st))
00369     {
00370       fsal_status_to_string(fsal_status_buf, st);
00371       fprintf(output, "Error executing FSAL_BuildExportContext: %s\n", fsal_status_buf);
00372       return st.major;
00373     }
00374 
00375   /* get user's credentials */
00376 
00377   st = FSAL_InitClientContext(&context->context);
00378 
00379   if(FSAL_IS_ERROR(st))
00380     {
00381       fsal_status_to_string(fsal_status_buf, st);
00382       fprintf(output, "Error executing FSAL_InitClientContext: %s\n", fsal_status_buf);
00383       return st.major;
00384     }
00385 
00386   uid = getuid();
00387   pw_struct = getpwuid(uid);
00388 
00389   if(pw_struct == NULL)
00390     {
00391       fprintf(output, "Unknown uid %u\n", uid);
00392       return errno;
00393     }
00394 
00395   st = FSAL_GetClientContext(&context->context, &context->exp_context,
00396                              uid, pw_struct->pw_gid, NULL, 0);
00397 
00398   if(FSAL_IS_ERROR(st))
00399     {
00400       fsal_status_to_string(fsal_status_buf, st);
00401       fprintf(output, "Error executing FSAL_GetUserCred: %s\n", fsal_status_buf);
00402       return st.major;
00403     }
00404 
00405   /* get root file handle */
00406 
00407   /* lookup */
00408 
00409   st = FSAL_lookup(NULL, NULL, &context->context, &hdl_dir, NULL);
00410 
00411   if(FSAL_IS_ERROR(st))
00412     {
00413       fsal_status_to_string(fsal_status_buf, st);
00414       fprintf(output, "Error executing FSAL_lookup: %s\n", fsal_status_buf);
00415       return st.major;
00416     }
00417 
00418   /* save root handle */
00419 
00420   context->current_dir = hdl_dir;
00421   context->is_thread_ok = TRUE;
00422 
00423   strcpy(context->current_path, "/");
00424 
00425   snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &context->current_dir);
00426   if(flag_v)
00427     fprintf(output, "Current directory is \"%s\" (@%s)\n", context->current_path, buff);
00428 
00429   return 0;
00430 
00431 }
00432 
00433 void fsal_layer_SetLogLevel(int log_lvl)
00434 {
00435 #ifdef OLD_LOGGING
00436   log_stream_t *curr;
00437 
00438   /* mutex pour proteger le descriptor de log */
00439   pthread_mutex_lock(&mutex_log);
00440 
00441   /* first time */
00442   if(log_level == -1)
00443     {
00444       log_level = log_lvl;
00445       voie.fd = fileno(stderr);
00446       AddLogStreamJd(&log_desc, V_FD, voie, log_level, SUP);
00447     }
00448   else
00449     {
00450       log_level = log_lvl;
00451       /* changing log level */
00452       curr = log_desc.liste_voies;
00453       while(curr)
00454         {
00455           curr->niveau = log_level;
00456           curr = curr->suivante;
00457         }
00458     }
00459 
00460   pthread_mutex_unlock(&mutex_log);
00461 #endif
00462 }
00463 
00464 static void getopt_init()
00465 {
00466   Opterr = 0;                   /* disables Getopt error message */
00467   /* reinits Getopt processing */
00468   Optind = 1;
00469 }
00470 
00471 int fsal_init(char *filename, int flag_v, FILE * output)
00472 {
00473   config_file_t config_file;
00474 
00475   /* FSAL init parameters */
00476   fsal_parameter_t init_param;
00477   fsal_status_t st;
00478 
00479   /* thread context */
00480   cmdfsal_thr_info_t *context;
00481 
00482   /* Initializes the FSAL */
00483   char fsal_path_lib[MAXPATHLEN];
00484 
00485 /* TODO - This code is now broken by the new fsal api which is still
00486  * in flux.  Commented some stale stuff out to build at this point.
00487  * come back to this when api settles down enough.
00488  */
00489 
00490   /* Load the FSAL library (if needed) */
00491   if(!FSAL_LoadLibrary(fsal_path_lib))
00492     {
00493       fprintf(stderr, "NFS MAIN: Could not load FSAL dynamic library %s\n",
00494               fsal_path_lib);
00495       exit(1);
00496     }
00497 
00498   /* Get the FSAL functions */
00499   FSAL_LoadFunctions();
00500 
00501   /* Get the FSAL consts */
00502   FSAL_LoadConsts();
00503 
00504   /* use FSAL error family. */
00505 
00506   AddFamilyError(ERR_FSAL, "FSAL related Errors", tab_errstatus_FSAL);
00507   AddFamilyError(ERR_POSIX, "POSIX Errors", tab_systeme_status);
00508 
00509   /* set configuration defaults */
00510 
00511   FSAL_SetDefault_FSAL_parameter(&init_param);
00512   FSAL_SetDefault_FS_common_parameter(&init_param);
00513   FSAL_SetDefault_FS_specific_parameter(&init_param);
00514 
00515   /* Parse config file */
00516 
00517   config_file = config_ParseFile(filename);
00518 
00519   if(!config_file)
00520     {
00521       fprintf(output, "init_fs: Error parsing %s: %s\n", filename, config_GetErrorMsg());
00522       return -1;
00523     }
00524 
00525   /* Load FSAL configuration from file configuration */
00526 
00527   st = FSAL_load_FSAL_parameter_from_conf(config_file, &init_param);
00528 
00529   if(FSAL_IS_ERROR(st))
00530     {
00531       if(st.major == ERR_FSAL_NOENT)
00532         {
00533           fprintf(output, "Missing FSAL stanza in config file\n");
00534         }
00535       else
00536         {
00537           fprintf(output, "Error executing FSAL_load_FSAL_parameter_from_conf:");
00538           print_fsal_status(output, st);
00539           fprintf(output, "\n");
00540           return st.major;
00541         }
00542     }
00543 
00544   st = FSAL_load_FS_common_parameter_from_conf(config_file, &init_param);
00545 
00546   if(FSAL_IS_ERROR(st))
00547     {
00548       if(st.major == ERR_FSAL_NOENT)
00549         {
00550           fprintf(output, "Missing FS common stanza in config file\n");
00551         }
00552       else
00553         {
00554           fprintf(output, "Error executing FSAL_load_FS_common_parameter_from_conf:");
00555           print_fsal_status(output, st);
00556           fprintf(output, "\n");
00557           return st.major;
00558         }
00559     }
00560 
00561   st = FSAL_load_FS_specific_parameter_from_conf(config_file, &init_param);
00562 
00563   if(FSAL_IS_ERROR(st))
00564     {
00565       if(st.major == ERR_FSAL_NOENT)
00566         {
00567           fprintf(output, "Missing FS specific stanza in config file\n");
00568         }
00569       else
00570         {
00571           fprintf(output, "Error executing FSAL_load_FS_specific_parameter_from_conf:");
00572           print_fsal_status(output, st);
00573           fprintf(output, "\n");
00574           return st.major;
00575         }
00576     }
00577 
00578   /* Free config struct */
00579   config_Free(config_file);
00580 
00581 #ifdef OLD_LOGGING
00582   /* overide log descriptor for FSAL */
00583   init_param.fsal_info.log_outputs = log_desc;
00584 #endif
00585 
00586   /* Initialization */
00587 
00588   if(flag_v)
00589     fprintf(output, "Filesystem initialization...\n");
00590 
00591   st = FSAL_Init(&init_param);
00592 
00593   if(FSAL_IS_ERROR(st))
00594     {
00595 
00596       fprintf(output, "Error executing FSAL_Init:");
00597       print_fsal_status(output, st);
00598       fprintf(output, "\n");
00599       return st.major;
00600 
00601     }
00602 
00603   is_loaded = TRUE;
00604 
00605   /* initialize current thread */
00606 
00607   context = GetFSALCmdContext();
00608 
00609   if(context->is_thread_ok != TRUE)
00610     {
00611       int rc;
00612       rc = Init_Thread_Context(output, context, flag_v);
00613       if(rc != 0)
00614         return rc;
00615     }
00616 
00617   return 0;
00618 }
00619 
00621 int fn_fsal_init_fs(int argc,   /* IN : number of args in argv */
00622                     char **argv,        /* IN : arg list               */
00623                     FILE * output)      /* IN : output stream          */
00624 {
00625   int rc;
00626 
00627   char format[] = "hv";
00628 
00629   const char help_init[] =
00630       "usage: init_fs [options] <ganesha_config_file>\n"
00631       "options :\n" "\t-h print this help\n" "\t-v verbose mode\n";
00632 
00633   int option;
00634   int flag_v = 0;
00635   int flag_h = 0;
00636   int err_flag = 0;
00637   char *filename = NULL;
00638 
00639   /* analysing options */
00640   getopt_init();
00641   while((option = Getopt(argc, argv, format)) != -1)
00642     {
00643       switch (option)
00644         {
00645         case 'v':
00646           if(flag_v)
00647             fprintf(output,
00648                     "init_fs: warning: option 'v' has been specified more than once.\n");
00649           else
00650             flag_v++;
00651           break;
00652         case 'h':
00653           if(flag_h)
00654             fprintf(output,
00655                     "init_fs: warning: option 'h' has been specified more than once.\n");
00656           else
00657             flag_h++;
00658           break;
00659         case '?':
00660           fprintf(output, "init_fs: unknown option : %c\n", Optopt);
00661           err_flag++;
00662           break;
00663         }
00664     }
00665 
00666   if(flag_h)
00667     {
00668       fprintf(output, help_init);
00669       return 0;
00670     }
00671 
00672   /* verifies mandatory argument */
00673 
00674   if(Optind != (argc - 1))
00675     {
00676       /* too much or not enough arguments */
00677       err_flag++;
00678     }
00679   else
00680     {
00681       filename = argv[Optind];
00682     }
00683 
00684   if(err_flag)
00685     {
00686       fprintf(output, help_init);
00687       return -1;
00688     }
00689 
00690   rc = fsal_init(filename, flag_v, output);
00691 
00692   return rc;
00693 }
00694 
00697 int fn_fsal_pwd(int argc,       /* IN : number of args in argv */
00698                 char **argv,    /* IN : arg list               */
00699                 FILE * output   /* IN : output stream          */
00700     )
00701 {
00702 
00703   cmdfsal_thr_info_t *context;
00704 
00705   /* is the fs initialized ? */
00706   if(!is_loaded)
00707     {
00708       fprintf(output, "Error: filesystem not initialized\n");
00709       return -1;
00710     }
00711 
00712   /* initialize current thread */
00713 
00714   context = GetFSALCmdContext();
00715 
00716   if(context->is_thread_ok != TRUE)
00717     {
00718       int rc;
00719       rc = Init_Thread_Context(output, context, 0);
00720       if(rc != 0)
00721         return rc;
00722     }
00723 
00724   {
00725     char buff[2 * sizeof(fsal_handle_t) + 1];
00726     snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &context->current_dir);
00727 
00728     fprintf(output, "Current directory is \"%s\" (@%s)\n", context->current_path, buff);
00729 
00730   }
00731 
00732   return 0;
00733 
00734 }
00735 
00736 /* solves a relative or absolute path */
00737 
00738 int solvepath(char *io_global_path, int size_global_path,       /* [IN-OUT] global path     */
00739               char *i_spec_path,        /* [IN] user specified path */
00740               fsal_handle_t i_current_handle,   /* [IN] current directory handle   */
00741               fsal_handle_t * new_handle,       /* [OUT] target object handle      */
00742               FILE * output)
00743 {
00744 
00745   char str_path[FSAL_MAX_PATH_LEN];
00746   cmdfsal_thr_info_t *context;
00747 
00748   context = GetFSALCmdContext();
00749 
00750   if(context->is_thread_ok != TRUE)
00751     {
00752       int rc;
00753       rc = Init_Thread_Context(output, context, 0);
00754       if(rc != 0)
00755         return rc;
00756     }
00757 
00758   /* local copy */
00759   memset( str_path, 0, FSAL_MAX_PATH_LEN ) ;
00760   strncpy(str_path, i_spec_path, FSAL_MAX_PATH_LEN);
00761 
00762   if(str_path[0] == '@')
00763     /* It is a file handle */
00764     {
00765       int rc;
00766 
00767       rc = sscanHandle(new_handle, str_path + 1);
00768 
00769       if(rc <= 0)
00770         {
00771           fprintf(output, "Invalid FileHandle: %s\n", str_path);
00772           return -1;
00773         }
00774 
00775       if(str_path[rc + 1] != '\0')
00776         {
00777           fprintf(output, "Invalid FileHandle: %s\n", str_path);
00778           return -1;
00779         }
00780 
00781       strncpy(io_global_path, str_path, size_global_path);
00782 
00783       return 0;
00784 
00785     }
00786   else if(str_path[0] == '/')
00787     /* absolute path, proceed a lookupPath */
00788     {
00789       fsal_path_t path;
00790       fsal_status_t st;
00791       fsal_handle_t tmp_hdl;
00792 
00793       if(FSAL_IS_ERROR(st = FSAL_str2path(str_path, FSAL_MAX_PATH_LEN, &path)))
00794         {
00795           fprintf(output, "Error executing FSAL_str2path:");
00796           print_fsal_status(output, st);
00797           fprintf(output, "\n");
00798           return st.major;
00799         }
00800 
00801       if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &context->context, &tmp_hdl, NULL)))
00802         {
00803           fprintf(output, "Error executing FSAL_lookupPath:");
00804           print_fsal_status(output, st);
00805           fprintf(output, "\n");
00806           return st.major;
00807         }
00808 
00809       /* cleans path */
00810       clean_path(str_path, FSAL_MAX_PATH_LEN);
00811 
00812       strncpy(io_global_path, str_path, size_global_path);
00813       *new_handle = tmp_hdl;
00814 
00815       return 0;
00816 
00817     }
00818   else
00819     /* relative path, proceed a step by step lookup */
00820     {
00821       fsal_name_t name;
00822       fsal_status_t st;
00823       fsal_handle_t old_hdl = i_current_handle;
00824       fsal_handle_t tmp_hdl;
00825       char tmp_path[FSAL_MAX_PATH_LEN];
00826       char *next_name = str_path;
00827       char *curr = str_path;
00828       int last = 0;
00829 
00830       tmp_path[0] = '\0';       /* empty string */
00831 
00832       do
00833         {
00834 
00835           /* tokenize to the next '/' */
00836           while((*curr != '\0') && (*curr != '/'))
00837             curr++;
00838 
00839           if(!(*curr))
00840             last = 1;           /* remembers if it was the last dir */
00841           *curr = '\0';
00842 
00843           /* build the name */
00844           if(FSAL_IS_ERROR(st = FSAL_str2name(next_name, FSAL_MAX_PATH_LEN, &name)))
00845             {
00846               fprintf(output, "Error executing FSAL_str2name:");
00847               print_fsal_status(output, st);
00848               fprintf(output, "\n");
00849               return st.major;
00850             }
00851 
00852           /* lookup this name */
00853           if(FSAL_IS_ERROR
00854              (st = FSAL_lookup(&old_hdl, &name, &context->context, &tmp_hdl, NULL)))
00855             {
00856               fprintf(output, "Error executing FSAL_lookup:");
00857               print_fsal_status(output, st);
00858               fprintf(output, "\n");
00859               return st.major;
00860             }
00861 
00862           /* if handles are the same, we are at fileset root,
00863            * so, don't modify the path.
00864            * Else, we contatenate them.
00865            */
00866           if(FSAL_handlecmp(&old_hdl, &tmp_hdl, &st) != 0)
00867             {
00868               /* updates current handle */
00869               old_hdl = tmp_hdl;
00870 
00871               /* adds /name at the end of the path */
00872               strncat(tmp_path, "/", FSAL_MAX_PATH_LEN);
00873               strncat(tmp_path, next_name, FSAL_MAX_PATH_LEN - strlen(tmp_path));
00874             }
00875 
00876           /* updates cursors */
00877           if(!last)
00878             {
00879               curr++;
00880               next_name = curr;
00881               /* ignore successive slashes */
00882               while((*curr != '\0') && (*curr == '/'))
00883                 {
00884                   curr++;
00885                   next_name = curr;
00886                 }
00887               if(!(*curr))
00888                 last = 1;       /* it is the last dir */
00889             }
00890 
00891         }
00892       while(!last);
00893 
00894       /* everything is OK, apply changes */
00895 
00896       strncat(io_global_path, tmp_path, size_global_path);
00897       clean_path(io_global_path, size_global_path);
00898 
00899       *new_handle = old_hdl;
00900 
00901       return 0;
00902 
00903     }
00904 
00905 }
00906 
00908 int fn_fsal_cd(int argc,        /* IN : number of args in argv */
00909                char **argv,     /* IN : arg list               */
00910                FILE * output    /* IN : output stream          */
00911     )
00912 {
00913 
00914   static char help_cd[] = "usage: cd <path>\n";
00915 
00916   char glob_path[FSAL_MAX_PATH_LEN];
00917   fsal_handle_t new_hdl;
00918   fsal_attrib_list_t attrs;
00919   fsal_status_t st;
00920   int rc;
00921 
00922   cmdfsal_thr_info_t *context;
00923 
00924   /* is the fs initialized ? */
00925   if(!is_loaded)
00926     {
00927       fprintf(output, "Error: filesystem not initialized\n");
00928       return -1;
00929     }
00930 
00931   /* initialize current thread */
00932 
00933   context = GetFSALCmdContext();
00934 
00935   if(context->is_thread_ok != TRUE)
00936     {
00937       int rc;
00938       rc = Init_Thread_Context(output, context, 0);
00939       if(rc != 0)
00940         return rc;
00941     }
00942 
00943   /* Exactly one arg expected */
00944   if(argc != 2)
00945     {
00946       fprintf(output, help_cd, NULL);
00947       return -1;
00948     }
00949 
00950   /* is it a relative or absolute path. */
00951   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
00952 
00953   if((rc =
00954      solvepath(glob_path, FSAL_MAX_PATH_LEN,
00955                argv[1], context->current_dir, &new_hdl, output)))
00956     return rc;
00957 
00958   /* verify if the object is a directory */
00959   FSAL_CLEAR_MASK(attrs.asked_attributes);
00960   FSAL_SET_MASK(attrs.asked_attributes,
00961                 FSAL_ATTR_TYPE | FSAL_ATTR_MODE | FSAL_ATTR_GROUP | FSAL_ATTR_OWNER);
00962 
00963   if(FSAL_IS_ERROR(st = FSAL_getattrs(&new_hdl, &context->context, &attrs)))
00964     {
00965       fprintf(output, "Error executing FSAL_getattrs:");
00966       print_fsal_status(output, st);
00967       fprintf(output, "\n");
00968       return st.major;
00969     }
00970 
00971   if(attrs.type != FSAL_TYPE_DIR)
00972     {
00973       fprintf(output, "Error: %s is not a directory\n", glob_path);
00974       return ENOTDIR;
00975     }
00976 
00977   if(FSAL_IS_ERROR(st = FSAL_test_access(&context->context, FSAL_X_OK, &attrs)))
00978     {
00979       fprintf(output, "Error: %s: permission denied.\n", glob_path);
00980       return st.major;
00981     }
00982 
00983 /*  if (FSAL_IS_ERROR(st = FSAL_access(&new_hdl,&contexte,FSAL_X_OK,&attrs))){
00984     fprintf(output,"Error: %s: permission denied.\n",);
00985     return st.major;
00986   }*/
00987 
00988   /* if so, apply changes */
00989   strncpy(context->current_path, glob_path, FSAL_MAX_PATH_LEN);
00990   context->current_dir = new_hdl;
00991 
00992   {
00993     char buff[2 * sizeof(fsal_handle_t) + 1];
00994     snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &context->current_dir);
00995 
00996     fprintf(output, "Current directory is \"%s\" (@%s)\n", context->current_path, buff);
00997   }
00998 
00999   return 0;
01000 
01001 }
01002 
01004 int fn_fsal_stat(int argc,      /* IN : number of args in argv */
01005                  char **argv,   /* IN : arg list               */
01006                  FILE * output  /* IN : output stream          */
01007     )
01008 {
01009 
01010   char format[] = "hv";
01011 
01012   const char help_stat[] = "usage: stat [-h][-v] <file>\n";
01013 
01014   char glob_path[FSAL_MAX_PATH_LEN];
01015   fsal_handle_t new_hdl;
01016   fsal_attrib_list_t attrs;
01017   fsal_status_t st;
01018   int rc, option;
01019   int flag_v = 0;
01020   int flag_h = 0;
01021   int err_flag = 0;
01022   char *file = NULL;
01023 
01024   cmdfsal_thr_info_t *context;
01025 
01026   /* is the fs initialized ? */
01027   if(!is_loaded)
01028     {
01029       fprintf(output, "Error: filesystem not initialized\n");
01030       return -1;
01031     }
01032 
01033   /* initialize current thread */
01034 
01035   context = GetFSALCmdContext();
01036 
01037   if(context->is_thread_ok != TRUE)
01038     {
01039       int rc;
01040       rc = Init_Thread_Context(output, context, 0);
01041       if(rc != 0)
01042         return rc;
01043     }
01044 
01045   /* analysing options */
01046   getopt_init();
01047   while((option = Getopt(argc, argv, format)) != -1)
01048     {
01049       switch (option)
01050         {
01051         case 'v':
01052           if(flag_v)
01053             fprintf(output,
01054                     "stat: warning: option 'v' has been specified more than once.\n");
01055           else
01056             flag_v++;
01057           break;
01058         case 'h':
01059           if(flag_h)
01060             fprintf(output,
01061                     "stat: warning: option 'h' has been specified more than once.\n");
01062           else
01063             flag_h++;
01064           break;
01065         case '?':
01066           fprintf(output, "stat: unknown option : %c\n", Optopt);
01067           err_flag++;
01068           break;
01069         }
01070     }
01071 
01072   if(flag_h)
01073     {
01074       fprintf(output, help_stat);
01075       return 0;
01076     }
01077 
01078   /* Exactly one arg expected */
01079   if(Optind != (argc - 1))
01080     {
01081       err_flag++;
01082     }
01083   else
01084     {
01085       file = argv[Optind];
01086     }
01087 
01088   if(err_flag)
01089     {
01090       fprintf(output, help_stat);
01091       return -1;
01092     }
01093 
01094   /* copy current path. */
01095   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
01096 
01097   /* retrieves object handle */
01098   if((rc =
01099      solvepath(glob_path, FSAL_MAX_PATH_LEN,
01100                file, context->current_dir, &new_hdl, output)))
01101     return rc;
01102 
01103   /* retrieve supported attributes */
01104   FSAL_CLEAR_MASK(attrs.asked_attributes);
01105   FSAL_SET_MASK(attrs.asked_attributes, FSAL_ATTR_SUPPATTR);
01106 
01107   if(FSAL_IS_ERROR(st = FSAL_getattrs(&new_hdl, &context->context, &attrs)))
01108     {
01109       fprintf(output, "Error executing FSAL_getattrs:");
01110       print_fsal_status(output, st);
01111       fprintf(output, "\n");
01112       return st.major;
01113     }
01114 
01115   /* print supported attributes if verbose flag is set */
01116   if(flag_v)
01117     {
01118       fprintf(output, "Supported attributes :\n");
01119       print_fsal_attrib_mask(attrs.supported_attributes, output);
01120       fprintf(output, "\nAttributes :\n");
01121     }
01122 
01123   /* getting all supported attributes */
01124   attrs.asked_attributes = attrs.supported_attributes;
01125 
01126   if(FSAL_IS_ERROR(st = FSAL_getattrs(&new_hdl, &context->context, &attrs)))
01127     {
01128       fprintf(output, "Error executing FSAL_getattrs:");
01129       print_fsal_status(output, st);
01130       fprintf(output, "\n");
01131       return st.major;
01132     }
01133 
01134   /* print file attributes */
01135   print_fsal_attributes(attrs, output);
01136 
01137   return 0;
01138 
01139 }
01140 
01142 int fn_fsal_lsxattrs(int argc,  /* IN : number of args in argv */
01143                      char **argv,       /* IN : arg list               */
01144                      FILE * output      /* IN : output stream          */
01145     )
01146 {
01147   char fsal_status_buf[256];
01148 
01149   char format[] = "hv";
01150 
01151   const char help_lsxattr[] = "usage: lsxattrs [-h][-v] <path>\n";
01152 
01153   char glob_path[FSAL_MAX_PATH_LEN];
01154   fsal_handle_t new_hdl;
01155   fsal_status_t st;
01156   int rc, option;
01157   int flag_v = 0;
01158   int flag_h = 0;
01159   int err_flag = 0;
01160   char *file = NULL;
01161 
01162   unsigned int cookie;
01163   fsal_xattrent_t xattr_array[256];
01164   unsigned int nb_returned;
01165   int eol;
01166 
01167   cmdfsal_thr_info_t *context;
01168 
01169   /* is the fs initialized ? */
01170   if(!is_loaded)
01171     {
01172       fprintf(output, "Error: filesystem not initialized\n");
01173       return -1;
01174     }
01175 
01176   /* initialize current thread */
01177 
01178   context = GetFSALCmdContext();
01179 
01180   if(context->is_thread_ok != TRUE)
01181     {
01182       int rc;
01183       rc = Init_Thread_Context(output, context, 0);
01184       if(rc != 0)
01185         return rc;
01186     }
01187 
01188   /* analysing options */
01189   getopt_init();
01190   while((option = Getopt(argc, argv, format)) != -1)
01191     {
01192       switch (option)
01193         {
01194         case 'v':
01195           if(flag_v)
01196             fprintf(output,
01197                     "lsxattrs: warning: option 'v' has been specified more than once.\n");
01198           else
01199             flag_v++;
01200           break;
01201         case 'h':
01202           if(flag_h)
01203             fprintf(output,
01204                     "lsxattrs: warning: option 'h' has been specified more than once.\n");
01205           else
01206             flag_h++;
01207           break;
01208         case '?':
01209           fprintf(output, "lsxattrs: unknown option : %c\n", Optopt);
01210           err_flag++;
01211           break;
01212         }
01213     }
01214 
01215   if(flag_h)
01216     {
01217       fprintf(output, help_lsxattr);
01218       return 0;
01219     }
01220 
01221   /* Exactly one arg expected */
01222   if(Optind != (argc - 1))
01223     {
01224       err_flag++;
01225     }
01226   else
01227     {
01228       file = argv[Optind];
01229     }
01230 
01231   if(err_flag)
01232     {
01233       fprintf(output, help_lsxattr);
01234       return -1;
01235     }
01236 
01237   /* copy current path. */
01238   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
01239 
01240   /* retrieves object handle */
01241   if((rc =
01242      solvepath(glob_path, FSAL_MAX_PATH_LEN,
01243                file, context->current_dir, &new_hdl, output)))
01244     return rc;
01245 
01246   /* list extended attributes */
01247 
01248   cookie = XATTRS_READLIST_FROM_BEGINNING;
01249   eol = FALSE;
01250 
01251   while(!eol)
01252     {
01253       unsigned int index;
01254 
01255       st = FSAL_ListXAttrs(&new_hdl, cookie, &context->context,
01256                            xattr_array, 256, &nb_returned, &eol);
01257 
01258       if(FSAL_IS_ERROR(st))
01259         {
01260           fsal_status_to_string(fsal_status_buf, st);
01261           fprintf(output, "Error executing FSAL_ListXAttrs: %s\n", fsal_status_buf);
01262           return st.major;
01263         }
01264 
01265       /* list attributes */
01266 
01267       for(index = 0; index < nb_returned; index++)
01268         {
01269           if(flag_v)
01270             /* print all attribute's info */
01271             fprintf(output, "%u: %s\n", xattr_array[index].xattr_id,
01272                     xattr_array[index].xattr_name.name);
01273           else
01274             /* print only attribute's name */
01275             fprintf(output, "%s\n", xattr_array[index].xattr_name.name);
01276 
01277           cookie = xattr_array[index].xattr_cookie;
01278         }
01279 
01280     }
01281 
01282   return 0;
01283 
01284 }
01285 
01287 int fn_fsal_getxattr(int argc,  /* IN : number of args in argv */
01288                      char **argv,       /* IN : arg list               */
01289                      FILE * output      /* IN : output stream          */
01290     )
01291 {
01292   char format[] = "hvaxn";
01293 
01294   const char help_getxattr[] =
01295       "usage: getxattr [-hv] [-a|-n|-x] <path> <attr_name>\n"
01296       "options :\n"
01297       "\t-h print this help\n"
01298       "\t-v verbose mode\n"
01299       "\t-a display attribute value as ascii\n"
01300       "\t-n display attribute value as numeric\n"
01301       "\t-x display attribute value as hexa\n";
01302 
01303   char glob_path[FSAL_MAX_PATH_LEN];
01304   fsal_handle_t new_hdl;
01305   fsal_status_t st;
01306   int rc, option;
01307   int flag_v = 0;
01308   int flag_h = 0;
01309   int flag_x = 0;
01310   int flag_n = 0;
01311   int flag_a = 0;
01312   int err_flag = 0;
01313   char *file = NULL;
01314   char *attrname = NULL;
01315 
01316   fsal_name_t attrnamefsal;
01317   char buffer[4096];
01318   size_t returned;
01319   unsigned int index;
01320 
01321   cmdfsal_thr_info_t *context;
01322 
01323   /* is the fs initialized ? */
01324   if(!is_loaded)
01325     {
01326       fprintf(output, "Error: filesystem not initialized\n");
01327       return -1;
01328     }
01329 
01330   /* initialize current thread */
01331 
01332   context = GetFSALCmdContext();
01333 
01334   if(context->is_thread_ok != TRUE)
01335     {
01336       int rc;
01337       rc = Init_Thread_Context(output, context, 0);
01338       if(rc != 0)
01339         return rc;
01340     }
01341 
01342   /* analysing options */
01343   getopt_init();
01344   while((option = Getopt(argc, argv, format)) != -1)
01345     {
01346       switch (option)
01347         {
01348         case 'v':
01349           if(flag_v)
01350             fprintf(output,
01351                     "getxattr: warning: option 'v' has been specified more than once.\n");
01352           else
01353             flag_v++;
01354           break;
01355         case 'a':
01356           if(flag_a)
01357             fprintf(output,
01358                     "getxattr: warning: option 'a' has been specified more than once.\n");
01359           else
01360             flag_a++;
01361           break;
01362         case 'x':
01363           if(flag_x)
01364             fprintf(output,
01365                     "getxattr: warning: option 'x' has been specified more than once.\n");
01366           else
01367             flag_x++;
01368           break;
01369         case 'n':
01370           if(flag_n)
01371             fprintf(output,
01372                     "getxattr: warning: option 'n' has been specified more than once.\n");
01373           else
01374             flag_n++;
01375           break;
01376         case 'h':
01377           if(flag_h)
01378             fprintf(output,
01379                     "getxattr: warning: option 'h' has been specified more than once.\n");
01380           else
01381             flag_h++;
01382           break;
01383         case '?':
01384           fprintf(output, "getxattr: unknown option : %c\n", Optopt);
01385           err_flag++;
01386           break;
01387         }
01388     }
01389 
01390   if(flag_h)
01391     {
01392       fprintf(output, help_getxattr);
01393       return 0;
01394     }
01395 
01396   if(flag_x + flag_n + flag_a > 1)
01397     {
01398       fprintf(output, "getxattr: options -x, -a and -n are not compatible\n");
01399       fprintf(output, help_getxattr);
01400       return -1;
01401     }
01402 
01403   /* Exactly 2 args expected */
01404   if(Optind != (argc - 2))
01405     {
01406       err_flag++;
01407     }
01408   else
01409     {
01410       file = argv[Optind];
01411       attrname = argv[Optind + 1];
01412     }
01413 
01414   if(err_flag)
01415     {
01416       fprintf(output, help_getxattr);
01417       return -1;
01418     }
01419 
01420   /* copy current path. */
01421   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
01422 
01423   /* retrieves object handle */
01424   if((rc =
01425      solvepath(glob_path, FSAL_MAX_PATH_LEN,
01426                file, context->current_dir, &new_hdl, output)))
01427     return rc;
01428 
01429   /* create fsal_name_t */
01430   FSAL_str2name(attrname, 256, &attrnamefsal);
01431 
01432   memset(buffer, 0, sizeof(buffer));
01433 
01434   /* get extended attribute */
01435 
01436   st = FSAL_GetXAttrValueByName(&new_hdl, &attrnamefsal, &context->context,
01437                                 buffer, 4096, &returned);
01438 
01439   if(FSAL_IS_ERROR(st))
01440     {
01441       fprintf(output, "Error executing FSAL_GetXAttrValueByName:");
01442       print_fsal_status(output, st);
01443       fprintf(output, "\n");
01444       return st.major;
01445     }
01446 
01447   if(returned == 0)
01448     {
01449       fprintf(output, "(empty)\n");
01450       return 0;
01451     }
01452 
01453   /* display returned value */
01454 
01455   /* when no flags are given, try to determinate what it is */
01456 
01457   if(!flag_a && !flag_n && !flag_x)
01458     {
01459       /* is it ascii ? */
01460       if(strlen(buffer) == returned - 1 || strlen(buffer) == returned)
01461         {
01462           unsigned int i;
01463           char *str = buffer;
01464           int is_ascii = TRUE;
01465 
01466           for(i = 0; i < strlen(str); i++)
01467             {
01468               if(!isprint(str[i]) && !isspace(str[i]))
01469                 {
01470                   is_ascii = FALSE;
01471                   break;
01472                 }
01473             }
01474           if(is_ascii)
01475             flag_a = 1;
01476         }
01477 
01478       /* is it numeric */
01479       if(!flag_a)
01480         {
01481           if(returned == 1 || returned == 2 || returned == 4 || returned == 8)
01482             flag_n = 1;
01483           else
01484             flag_x = 1;
01485         }
01486     }
01487 
01488   if(flag_a)
01489     {
01490       if(strlen(buffer) > 0 && buffer[strlen(buffer) - 1] != '\n')
01491         fprintf(output, "%s\n", buffer);
01492       else
01493         fprintf(output, "%s", buffer);
01494     }
01495   else if(flag_n)
01496     {
01497       if(returned == 1)
01498         fprintf(output, "%hhu\n", buffer[0]);
01499       else if(returned == 2)
01500         fprintf(output, "%hu\n", *(buffer));
01501       else if(returned == 4)
01502         fprintf(output, "%u\n", *(buffer));
01503       else if(returned == 8)
01504         fprintf(output, "%llu\n", (long long unsigned int)*(buffer));
01505       else
01506         {
01507           for(index = 0; index < returned; index += 8)
01508             {
01509               unsigned long long *p64 = (unsigned long long *)(buffer + index);
01510               if(index == 0)
01511                 fprintf(output, "%llu", *p64);
01512               else
01513                 fprintf(output, ".%llu", *p64);
01514             }
01515           fprintf(output, "\n");
01516 
01517         }
01518 
01519     }
01520   else if(flag_x)               /* hexa */
01521     {
01522       fprintf(output, "0X");
01523       for(index = 0; index < returned; index++)
01524         {
01525           unsigned char val = buffer[index];
01526           fprintf(output, "%hhX", val);
01527         }
01528       fprintf(output, "\n");
01529 
01530     }
01531 
01532   return 0;
01533 
01534 }
01535 
01537 int fn_fsal_ls(int argc,        /* IN : number of args in argv */
01538                char **argv,     /* IN : arg list               */
01539                FILE * output)   /* IN : output stream          */
01540 {
01541 
01542   char format[] = "hvdlS";
01543 
01544   const char help_ls[] =
01545       "usage: ls [options] [name|path]\n"
01546       "options :\n"
01547       "\t-h print this help\n"
01548       "\t-v verbose mode\n"
01549       "\t-d print directory info instead of listing its content\n"
01550       "\t-l print standard UNIX attributes\n" "\t-S print all supported attributes\n";
01551 
01552   int option;
01553   int flag_v = 0;
01554   int flag_h = 0;
01555   int flag_d = 0;
01556   int flag_l = 0;
01557   int flag_S = 0;
01558   int err_flag = 0;
01559   char *str_name;
01560 
01561 //#define READDIR_SIZE FSAL_READDIR_SIZE
01562 #define READDIR_SIZE 10
01563 
01564   fsal_attrib_mask_t mask_needed;
01565   fsal_handle_t obj_hdl;
01566   fsal_dir_t dir;
01567   char glob_path[FSAL_MAX_PATH_LEN];
01568   fsal_attrib_list_t attrs;
01569   fsal_status_t st;
01570   fsal_cookie_t from, to;
01571   fsal_dirent_t entries[READDIR_SIZE];
01572   fsal_count_t number;
01573   fsal_boolean_t eod = FALSE;
01574   fsal_path_t symlink_path;
01575   int error = FALSE;
01576   int rc;
01577 
01578   cmdfsal_thr_info_t *context;
01579 
01580   /* analysing options */
01581   getopt_init();
01582   while((option = Getopt(argc, argv, format)) != -1)
01583     {
01584 
01585       switch (option)
01586         {
01587         case 'v':
01588           if(flag_v)
01589             fprintf(output,
01590                     "ls: warning: option 'v' has been specified more than once.\n");
01591           else
01592             flag_v++;
01593           break;
01594         case 'h':
01595           if(flag_h)
01596             fprintf(output,
01597                     "ls: warning: option 'h' has been specified more than once.\n");
01598           else
01599             flag_h++;
01600           break;
01601         case 'd':
01602           if(flag_d)
01603             fprintf(output,
01604                     "ls: warning: option 'd' has been specified more than once.\n");
01605           else
01606             flag_d++;
01607           break;
01608         case 'l':
01609           if(flag_l)
01610             fprintf(output,
01611                     "ls: warning: option 'l' has been specified more than once.\n");
01612           else
01613             flag_l++;
01614           break;
01615         case 'S':
01616           if(flag_S)
01617             fprintf(output,
01618                     "ls: warning: option 'S' has been specified more than once.\n");
01619           else
01620             flag_S++;
01621           break;
01622         case '?':
01623           fprintf(output, "ls: unknown option : %c\n", Optopt);
01624           err_flag++;
01625           break;
01626         }
01627 
01628     }
01629 
01630   if(flag_l + flag_S > 1)
01631     {
01632       fprintf(output, "ls: conflict between options l,S\n");
01633       err_flag++;
01634     }
01635 
01636   if(flag_h)
01637     {
01638       fprintf(output, help_ls);
01639       return 0;
01640     }
01641   if(err_flag)
01642     {
01643       fprintf(output, help_ls);
01644       return -1;
01645     }
01646 
01647   /* is the fs initialized ? */
01648   if(!is_loaded)
01649     {
01650       fprintf(output, "Error: filesystem not initialized\n");
01651       return -1;
01652     }
01653 
01654   /* initialize current thread */
01655 
01656   context = GetFSALCmdContext();
01657 
01658   if(context->is_thread_ok != TRUE)
01659     {
01660       int rc;
01661       rc = Init_Thread_Context(output, context, 0);
01662       if(rc != 0)
01663         return rc;
01664     }
01665 
01666   /* prepare needed attributes mask */
01667   FSAL_CLEAR_MASK(mask_needed);
01668   FSAL_SET_MASK(mask_needed, FSAL_ATTRS_MANDATORY);
01669 
01670   if(flag_l)
01671     FSAL_SET_MASK(mask_needed, FSAL_ATTRS_POSIX);
01672   else if(flag_S)
01673     mask_needed = 0xFFFFFFFFFFFFFFFFLL;
01674 
01675   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
01676 
01677   /* first, retrieve the argument (if any) */
01678   if(Optind == (argc - 1))
01679     {
01680       str_name = argv[Optind];
01681 
01682       /* retrieving handle */
01683       if((rc =
01684          solvepath(glob_path, FSAL_MAX_PATH_LEN,
01685                    str_name, context->current_dir, &obj_hdl, output)))
01686         return rc;
01687 
01688     }
01689   else
01690     {
01691       str_name = ".";
01692       obj_hdl = context->current_dir;
01693     }
01694 
01695   if(flag_v)
01696     fprintf(output, "proceeding ls on \"%s\"\n", glob_path);
01697 
01698   FSAL_CLEAR_MASK(attrs.asked_attributes);
01699   FSAL_SET_MASK(attrs.asked_attributes, FSAL_ATTR_SUPPATTR);
01700 
01701   if(FSAL_IS_ERROR(st = FSAL_getattrs(&obj_hdl, &context->context, &attrs)))
01702     {
01703       fprintf(output, "Error executing FSAL_getattrs:");
01704       print_fsal_status(output, st);
01705       fprintf(output, "\n");
01706       return st.major;
01707     }
01708 
01709   /* getting all needed attributes */
01710   attrs.asked_attributes = (attrs.supported_attributes & mask_needed);
01711 
01712   if(FSAL_IS_ERROR(st = FSAL_getattrs(&obj_hdl, &context->context, &attrs)))
01713     {
01714       fprintf(output, "Error executing FSAL_getattrs:");
01715       print_fsal_status(output, st);
01716       fprintf(output, "\n");
01717       return st.major;
01718     }
01719 
01720   /*
01721    * if the object is a file or a directoy with the -d option specified,
01722    * we only show its info and exit.
01723    */
01724   if((attrs.type != FSAL_TYPE_DIR) || flag_d)
01725     {
01726 
01727       if((attrs.type == FSAL_TYPE_LNK) && (flag_l))
01728         {
01729 
01730           if(FSAL_IS_ERROR
01731              (st = FSAL_readlink(&obj_hdl, &context->context, &symlink_path, NULL)))
01732             {
01733               fprintf(output, "Error executing FSAL_readlink:");
01734               print_fsal_status(output, st);
01735               fprintf(output, "\n");
01736               return st.major;
01737             }
01738 
01739         }
01740 
01741       if(flag_l)
01742         print_item_line(output, &attrs, str_name, symlink_path.path);
01743 
01744       else if(flag_S)
01745         {
01746 
01747           char tracebuff[2 * sizeof(fsal_handle_t) + 1];
01748           snprintHandle(tracebuff, 2 * sizeof(fsal_handle_t) + 1, &obj_hdl);
01749           fprintf(output, "%s (@%s):\n", str_name, tracebuff);
01750           print_fsal_attributes(attrs, output);
01751 
01752         }
01753       else                      /* only prints the name */
01754         fprintf(output, "%s\n", str_name);
01755 
01756       return 0;
01757     }
01758 
01759   /*
01760    * the current object is a directory, we have to list its element
01761    */
01762   if(FSAL_IS_ERROR(st = FSAL_opendir(&obj_hdl, &context->context, &dir, NULL)))
01763     {
01764       fprintf(output, "Error executing FSAL_opendir:");
01765       print_fsal_status(output, st);
01766       fprintf(output, "\n");
01767       return st.major;
01768     }
01769 
01770   FSAL_SET_COOKIE_BEGINNING(from);
01771 
01772   while(!error && !eod)
01773     {
01774       fsal_dirent_t *curr;
01775       char item_path[FSAL_MAX_PATH_LEN];
01776 
01777       if(FSAL_IS_ERROR
01778          (st =
01779           FSAL_readdir(&dir, from, attrs.supported_attributes & mask_needed,
01780                        READDIR_SIZE * sizeof(fsal_dirent_t), entries, &to, &number,
01781                        &eod)))
01782         {
01783           fprintf(output, "Error executing FSAL_readdir:");
01784           print_fsal_status(output, st);
01785           fprintf(output, "\n");
01786           error = st.major;
01787           number = 0;
01788         }
01789 
01790       if(flag_v)
01791         fprintf(output, "FSAL_readdir returned %u entries\n", (unsigned int)number);
01792 
01793       if(number > 0)
01794         {
01795           curr = entries;
01796           do
01797             {
01798               int len;
01799               len = strlen(str_name);
01800               if(!strcmp(str_name, "."))
01801                 strncpy(item_path, curr->name.name, FSAL_MAX_PATH_LEN);
01802               else if(str_name[len - 1] == '/')
01803                 snprintf(item_path, FSAL_MAX_PATH_LEN, "%s%s", str_name, curr->name.name);
01804               else
01805                 snprintf(item_path, FSAL_MAX_PATH_LEN, "%s/%s", str_name,
01806                          curr->name.name);
01807 
01808               if((curr->attributes.type == FSAL_TYPE_LNK) && (flag_l))
01809                 {
01810 
01811                   if(FSAL_IS_ERROR
01812                      (st =
01813                       FSAL_readlink(&curr->handle, &context->context, &symlink_path,
01814                                     NULL)))
01815                     {
01816                       fprintf(output, "Error executing FSAL_readlink:");
01817                       print_fsal_status(output, st);
01818                       fprintf(output, "\n");
01819                       return st.major;
01820                     }
01821 
01822                 }
01823 
01824               if(flag_l)
01825                 print_item_line(output, &(curr->attributes), item_path,
01826                                 symlink_path.path);
01827 
01828               else if(flag_S)
01829                 {
01830 
01831                   char tracebuff[2 * sizeof(fsal_handle_t) + 1];
01832                   snprintHandle(tracebuff, 2 * sizeof(fsal_handle_t) + 1, &curr->handle);
01833 
01834                   fprintf(output, "%s (@%s):\n", item_path, tracebuff);
01835                   print_fsal_attributes(curr->attributes, output);
01836 
01837                 }
01838               else              /* only prints the name */
01839                 fprintf(output, "%s\n", item_path);
01840 
01841             }
01842           while((curr = curr->nextentry));
01843         }
01844       /* preparing next call */
01845       from = to;
01846 
01847     }
01848 
01849   FSAL_closedir(&dir);
01850 
01851   return error;
01852 
01853 }                               /* fn_fsal_ls */
01854 
01856 int fn_fsal_callstat(int argc,  /* IN : number of args in argv */
01857                      char **argv,       /* IN : arg list               */
01858                      FILE * output      /* IN : output stream          */
01859     )
01860 {
01861 
01862   fsal_statistics_t call_stat;
01863   int i;
01864 
01865   const char help_stats[] = "usage: stats\n";
01866 
01867   /* is the fs initialized ? */
01868   if(!is_loaded)
01869     {
01870       fprintf(output, "Error: filesystem not initialized\n");
01871       return -1;
01872     }
01873 
01874   /* No args expected */
01875   if(argc != 1)
01876     {
01877       fprintf(output, help_stats);
01878       return -1;
01879     }
01880 
01881   /* retrieving current thread stats */
01882   FSAL_get_stats(&call_stat, FALSE);
01883 
01884   /* displaying stats */
01885   /* header: */
01886   fprintf(output,
01887           "Function             | Nb_Calls    | Success     | Retryable   | Unrecoverable\n");
01888   /* content */
01889   for(i = 0; i < FSAL_NB_FUNC; i++)
01890     fprintf(output, "%-20s | %11u | %11u | %11u | %11u\n",
01891             fsal_function_names[i],
01892             call_stat.func_stats.nb_call[i],
01893             call_stat.func_stats.nb_success[i],
01894             call_stat.func_stats.nb_err_retryable[i],
01895             call_stat.func_stats.nb_err_unrecover[i]);
01896 
01897   return 0;
01898 }
01899 
01901 int fn_fsal_su(int argc,        /* IN : number of args in argv */
01902                char **argv,     /* IN : arg list               */
01903                FILE * output    /* IN : output stream          */
01904     )
01905 {
01906 
01907   char *str_uid;
01908   fsal_uid_t uid;
01909   fsal_status_t st;
01910   struct passwd *pw_struct;
01911   int i;
01912 
01913 # define MAX_GRPS  128
01914   gid_t groups_tab[MAX_GRPS];
01915   int nb_grp;
01916 
01917   const char help_stats[] = "usage: su <uid>\n";
01918 
01919   cmdfsal_thr_info_t *context;
01920 
01921   /* is the fs initialized ? */
01922   if(!is_loaded)
01923     {
01924       fprintf(output, "Error: filesystem not initialized\n");
01925       return -1;
01926     }
01927 
01928   /* initialize current thread */
01929 
01930   context = GetFSALCmdContext();
01931 
01932   if(context->is_thread_ok != TRUE)
01933     {
01934       int rc;
01935       rc = Init_Thread_Context(output, context, 0);
01936       if(rc != 0)
01937         return rc;
01938     }
01939 
01940   /* UID arg expected */
01941   if(argc != 2)
01942     {
01943       fprintf(output, help_stats);
01944       return -1;
01945     }
01946   else
01947     {
01948       str_uid = argv[1];
01949     }
01950 
01951   if(isdigit(str_uid[0]))
01952     {
01953       if((uid = my_atoi(str_uid)) == (uid_t) - 1)
01954         {
01955           fprintf(output, "Error: invalid uid \"%s\"\n", str_uid);
01956           return -1;
01957         }
01958       pw_struct = getpwuid(uid);
01959     }
01960   else
01961     {
01962       pw_struct = getpwnam(str_uid);
01963     }
01964 
01965   if(pw_struct == NULL)
01966     {
01967       fprintf(output, "Unknown user %s\n", str_uid);
01968       return errno;
01969     }
01970 
01971   nb_grp = getugroups(MAX_GRPS, groups_tab, pw_struct->pw_name, pw_struct->pw_gid);
01972 
01973   fprintf(output, "Changing user to : %s ( uid = %d, gid = %d )\n",
01974           pw_struct->pw_name, pw_struct->pw_uid, pw_struct->pw_gid);
01975 
01976   if(nb_grp > 1)
01977     {
01978       fprintf(output, "altgroups = ");
01979       for(i = 1; i < nb_grp; i++)
01980         {
01981           if(i == 1)
01982             fprintf(output, "%d", groups_tab[i]);
01983           else
01984             fprintf(output, ", %d", groups_tab[i]);
01985         }
01986       fprintf(output, "\n");
01987     }
01988 
01989   st = FSAL_GetClientContext(&context->context, &context->exp_context,
01990                              pw_struct->pw_uid, pw_struct->pw_gid, groups_tab, nb_grp);
01991 
01992   if(FSAL_IS_ERROR(st))
01993     {
01994       fprintf(output, "Error executing FSAL_GetUserCred:");
01995       print_fsal_status(output, st);
01996       fprintf(output, "\n");
01997       return st.major;
01998     }
01999 
02000   fprintf(output, "Done.\n");
02001 
02002   return 0;
02003 
02004 }
02005 
02007 int fn_fsal_unlink(int argc,    /* IN : number of args in argv */
02008                    char **argv, /* IN : arg list               */
02009                    FILE * output        /* IN : output stream          */
02010     )
02011 {
02012 
02013   char format[] = "hv";
02014 
02015   const char help_unlink[] = "usage: unlink [-h][-v] <path>\n";
02016 
02017   char glob_path[FSAL_MAX_PATH_LEN];
02018   fsal_handle_t new_hdl;
02019   fsal_status_t st;
02020   int rc, option;
02021   int flag_v = 0;
02022   int flag_h = 0;
02023   int err_flag = 0;
02024 
02025   char tmp_path[FSAL_MAX_PATH_LEN];
02026   char *path;
02027   char *file;
02028 
02029   fsal_name_t objname;
02030 
02031   cmdfsal_thr_info_t *context;
02032 
02033   /* is the fs initialized ? */
02034   if(!is_loaded)
02035     {
02036       fprintf(output, "Error: filesystem not initialized\n");
02037       return -1;
02038     }
02039 
02040   /* initialize current thread */
02041 
02042   context = GetFSALCmdContext();
02043 
02044   if(context->is_thread_ok != TRUE)
02045     {
02046       int rc;
02047       rc = Init_Thread_Context(output, context, 0);
02048       if(rc != 0)
02049         return rc;
02050     }
02051 
02052   /* analysing options */
02053   getopt_init();
02054   while((option = Getopt(argc, argv, format)) != -1)
02055     {
02056       switch (option)
02057         {
02058         case 'v':
02059           if(flag_v)
02060             fprintf(output,
02061                     "unlink: warning: option 'v' has been specified more than once.\n");
02062           else
02063             flag_v++;
02064           break;
02065         case 'h':
02066           if(flag_h)
02067             fprintf(output,
02068                     "unlink: warning: option 'h' has been specified more than once.\n");
02069           else
02070             flag_h++;
02071           break;
02072         case '?':
02073           fprintf(output, "unlink: unknown option : %c\n", Optopt);
02074           err_flag++;
02075           break;
02076         }
02077     }
02078 
02079   if(flag_h)
02080     {
02081       fprintf(output, help_unlink);
02082       return 0;
02083     }
02084 
02085   /* Exactly 1 args expected */
02086   if(Optind != (argc - 1))
02087     {
02088       err_flag++;
02089     }
02090   else
02091     {
02092       strncpy(tmp_path, argv[Optind], FSAL_MAX_PATH_LEN);
02093       split_path(tmp_path, &path, &file);
02094     }
02095 
02096   if(err_flag)
02097     {
02098       fprintf(output, help_unlink);
02099       return -1;
02100     }
02101 
02102   /* copy current path. */
02103   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
02104 
02105   /* retrieves path handle */
02106   if((rc =
02107      solvepath(glob_path, FSAL_MAX_PATH_LEN,
02108                path, context->current_dir, &new_hdl, output)))
02109     return rc;
02110 
02111   /* create fsal_name_t */
02112   st = FSAL_str2name(file, 256, &objname);
02113   if(FSAL_IS_ERROR(st))
02114     {
02115       fprintf(output, "Error executing FSAL_str2name:");
02116       print_fsal_status(output, st);
02117       fprintf(output, "\n");
02118       return st.major;
02119     }
02120 
02121   if(FSAL_IS_ERROR(st = FSAL_unlink(&new_hdl, &objname, &context->context, NULL)))
02122     {
02123       fprintf(output, "Error executing FSAL_unlink:");
02124       print_fsal_status(output, st);
02125       fprintf(output, "\n");
02126       return st.major;
02127     }
02128 
02129   if(flag_v)
02130     fprintf(output, "%s/%s successfully unlinked\n", glob_path, file);
02131 
02132   return 0;
02133 
02134 }
02135 
02137 int fn_fsal_mkdir(int argc,     /* IN : number of args in argv */
02138                   char **argv,  /* IN : arg list               */
02139                   FILE * output /* IN : output stream          */
02140     )
02141 {
02142 
02143   char format[] = "hv";
02144 
02145   const char help_mkdir[] =
02146       "usage: mkdir [-h][-v] <path> <mode>\n"
02147       "       path: path of the directory to be created\n"
02148       "       mode: octal mode for the directory is to be created (ex: 755)\n";
02149 
02150   char glob_path[FSAL_MAX_PATH_LEN];
02151   fsal_handle_t new_hdl, subdir_hdl;
02152   fsal_status_t st;
02153   int rc, option;
02154   int flag_v = 0;
02155   int flag_h = 0;
02156   int err_flag = 0;
02157   int mode;
02158   fsal_accessmode_t fsalmode = 0755;
02159 
02160   char tmp_path[FSAL_MAX_PATH_LEN];
02161   char *path;
02162   char *file;
02163   char *strmode;
02164 
02165   fsal_name_t objname;
02166 
02167   cmdfsal_thr_info_t *context;
02168 
02169   /* is the fs initialized ? */
02170   if(!is_loaded)
02171     {
02172       fprintf(output, "Error: filesystem not initialized\n");
02173       return -1;
02174     }
02175 
02176   /* initialize current thread */
02177 
02178   context = GetFSALCmdContext();
02179 
02180   if(context->is_thread_ok != TRUE)
02181     {
02182       int rc;
02183       rc = Init_Thread_Context(output, context, 0);
02184       if(rc != 0)
02185         return rc;
02186     }
02187 
02188   /* analysing options */
02189   getopt_init();
02190   while((option = Getopt(argc, argv, format)) != -1)
02191     {
02192       switch (option)
02193         {
02194         case 'v':
02195           if(flag_v)
02196             fprintf(output,
02197                     "mkdir: warning: option 'v' has been specified more than once.\n");
02198           else
02199             flag_v++;
02200           break;
02201         case 'h':
02202           if(flag_h)
02203             fprintf(output,
02204                     "mkdir: warning: option 'h' has been specified more than once.\n");
02205           else
02206             flag_h++;
02207           break;
02208         case '?':
02209           fprintf(output, "mkdir: unknown option : %c\n", Optopt);
02210           err_flag++;
02211           break;
02212         }
02213     }
02214 
02215   if(flag_h)
02216     {
02217       fprintf(output, help_mkdir);
02218       return 0;
02219     }
02220 
02221   /* Exactly 2 args expected */
02222   if(Optind != (argc - 2))
02223     {
02224       err_flag++;
02225     }
02226   else
02227     {
02228 
02229       strncpy(tmp_path, argv[Optind], FSAL_MAX_PATH_LEN);
02230       split_path(tmp_path, &path, &file);
02231 
02232       strmode = argv[Optind + 1];
02233 
02234       /* converting mode string to FSAL mode string */
02235       mode = atomode(strmode);
02236       if(mode < 0)
02237         err_flag++;
02238       else
02239         {
02240 
02241           fsalmode = 0;
02242 
02243           if(mode & S_ISUID)
02244             fsalmode |= FSAL_MODE_SUID;
02245           if(mode & S_ISGID)
02246             fsalmode |= FSAL_MODE_SGID;
02247 
02248           if(mode & S_IRUSR)
02249             fsalmode |= FSAL_MODE_RUSR;
02250           if(mode & S_IWUSR)
02251             fsalmode |= FSAL_MODE_WUSR;
02252           if(mode & S_IXUSR)
02253             fsalmode |= FSAL_MODE_XUSR;
02254 
02255           if(mode & S_IRGRP)
02256             fsalmode |= FSAL_MODE_RGRP;
02257           if(mode & S_IWGRP)
02258             fsalmode |= FSAL_MODE_WGRP;
02259           if(mode & S_IXGRP)
02260             fsalmode |= FSAL_MODE_XGRP;
02261 
02262           if(mode & S_IROTH)
02263             fsalmode |= FSAL_MODE_ROTH;
02264           if(mode & S_IWOTH)
02265             fsalmode |= FSAL_MODE_WOTH;
02266           if(mode & S_IXOTH)
02267             fsalmode |= FSAL_MODE_XOTH;
02268 
02269         }
02270 
02271     }
02272 
02273   if(err_flag)
02274     {
02275       fprintf(output, help_mkdir);
02276       return -1;
02277     }
02278 
02279   /* copy current path. */
02280   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
02281 
02282   /* retrieves path handle */
02283   if((rc =
02284      solvepath(glob_path, FSAL_MAX_PATH_LEN,
02285                path, context->current_dir, &new_hdl, output)))
02286     return rc;
02287 
02288   /* create fsal_name_t */
02289   st = FSAL_str2name(file, 256, &objname);
02290   if(FSAL_IS_ERROR(st))
02291     {
02292       fprintf(output, "Error executing FSAL_str2name:");
02293       print_fsal_status(output, st);
02294       fprintf(output, "\n");
02295       return st.major;
02296     }
02297 
02298   if(FSAL_IS_ERROR(st = FSAL_mkdir(&new_hdl, &objname, &context->context,
02299                                    fsalmode, &subdir_hdl, NULL)))
02300     {
02301       fprintf(output, "Error executing FSAL_mkdir:");
02302       print_fsal_status(output, st);
02303       fprintf(output, "\n");
02304       return st.major;
02305     }
02306 
02307   if(flag_v)
02308     {
02309       char buff[2 * sizeof(fsal_handle_t) + 1];
02310       snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &subdir_hdl);
02311 
02312       fprintf(output, "%s/%s successfully created (@%s) \n", glob_path, file, buff);
02313 
02314     }
02315 
02316   return 0;
02317 
02318 }
02319 
02321 int fn_fsal_rename(int argc,    /* IN : number of args in argv */
02322                    char **argv, /* IN : arg list               */
02323                    FILE * output        /* IN : output stream          */
02324     )
02325 {
02326 
02327   char format[] = "hv";
02328 
02329   const char help_rename[] = "usage: rename [-h][-v] <src> <dest>\n";
02330 
02331   char src_glob_path[FSAL_MAX_PATH_LEN];
02332   char tgt_glob_path[FSAL_MAX_PATH_LEN];
02333 
02334   fsal_handle_t src_path_handle, tgt_path_handle;
02335   fsal_name_t src_name, tgt_name;
02336 
02337   fsal_status_t st;
02338   int rc, option;
02339   int flag_v = 0;
02340   int flag_h = 0;
02341   int err_flag = 0;
02342 
02343   char tmp_path1[FSAL_MAX_PATH_LEN];
02344   char tmp_path2[FSAL_MAX_PATH_LEN];
02345   char *src_path;
02346   char *src_file;
02347   char *tgt_path;
02348   char *tgt_file;
02349 
02350   cmdfsal_thr_info_t *context;
02351 
02352   /* is the fs initialized ? */
02353   if(!is_loaded)
02354     {
02355       fprintf(output, "Error: filesystem not initialized\n");
02356       return -1;
02357     }
02358 
02359   /* initialize current thread */
02360 
02361   context = GetFSALCmdContext();
02362 
02363   if(context->is_thread_ok != TRUE)
02364     {
02365       int rc;
02366       rc = Init_Thread_Context(output, context, 0);
02367       if(rc != 0)
02368         return rc;
02369     }
02370 
02371   /* analysing options */
02372   getopt_init();
02373   while((option = Getopt(argc, argv, format)) != -1)
02374     {
02375       switch (option)
02376         {
02377         case 'v':
02378           if(flag_v)
02379             fprintf(output,
02380                     "rename: warning: option 'v' has been specified more than once.\n");
02381           else
02382             flag_v++;
02383           break;
02384         case 'h':
02385           if(flag_h)
02386             fprintf(output,
02387                     "rename: warning: option 'h' has been specified more than once.\n");
02388           else
02389             flag_h++;
02390           break;
02391         case '?':
02392           fprintf(output, "rename: unknown option : %c\n", Optopt);
02393           err_flag++;
02394           break;
02395         }
02396     }
02397 
02398   if(flag_h)
02399     {
02400       fprintf(output, help_rename);
02401       return 0;
02402     }
02403 
02404   /* Exactly 2 args expected */
02405   if(Optind != (argc - 2))
02406     {
02407       err_flag++;
02408     }
02409   else
02410     {
02411 
02412       strncpy(tmp_path1, argv[Optind], FSAL_MAX_PATH_LEN);
02413       split_path(tmp_path1, &src_path, &src_file);
02414 
02415       strncpy(tmp_path2, argv[Optind + 1], FSAL_MAX_PATH_LEN);
02416       split_path(tmp_path2, &tgt_path, &tgt_file);
02417 
02418     }
02419 
02420   if(err_flag)
02421     {
02422       fprintf(output, help_rename);
02423       return -1;
02424     }
02425 
02426   if(flag_v)
02427     fprintf(output, "Renaming %s (dir %s) to %s (dir %s)\n",
02428             src_file, src_path, tgt_file, tgt_path);
02429 
02430   /* copy current path. */
02431   strncpy(src_glob_path, context->current_path, FSAL_MAX_PATH_LEN);
02432   strncpy(tgt_glob_path, context->current_path, FSAL_MAX_PATH_LEN);
02433 
02434   /* retrieves paths handles */
02435   if((rc =
02436      solvepath(src_glob_path, FSAL_MAX_PATH_LEN,
02437                src_path, context->current_dir, &src_path_handle, output)))
02438     return rc;
02439 
02440   if((rc =
02441      solvepath(tgt_glob_path, FSAL_MAX_PATH_LEN,
02442                tgt_path, context->current_dir, &tgt_path_handle, output)))
02443     return rc;
02444 
02445   /* create fsal_name_t */
02446 
02447   st = FSAL_str2name(src_file, 256, &src_name);
02448 
02449   if(FSAL_IS_ERROR(st))
02450     {
02451 
02452       fprintf(output, "Error executing FSAL_str2name:");
02453       print_fsal_status(output, st);
02454       fprintf(output, "\n");
02455       return st.major;
02456 
02457     }
02458 
02459   st = FSAL_str2name(tgt_file, 256, &tgt_name);
02460 
02461   if(FSAL_IS_ERROR(st))
02462     {
02463 
02464       fprintf(output, "Error executing FSAL_str2name:");
02465       print_fsal_status(output, st);
02466       fprintf(output, "\n");
02467       return st.major;
02468 
02469     }
02470 
02471   /* Rename operation */
02472 
02473   st = FSAL_rename(&src_path_handle,    /* IN */
02474                    &src_name,   /* IN */
02475                    &tgt_path_handle,    /* IN */
02476                    &tgt_name,   /* IN */
02477                    &context->context,   /* IN */
02478                    NULL, NULL);
02479 
02480   if(FSAL_IS_ERROR(st))
02481     {
02482 
02483       fprintf(output, "Error executing FSAL_rename:");
02484       print_fsal_status(output, st);
02485       fprintf(output, "\n");
02486       return st.major;
02487 
02488     }
02489 
02490   if(flag_v)
02491     fprintf(output, "%s/%s successfully renamed to %s/%s\n",
02492             src_glob_path, src_file, tgt_glob_path, tgt_file);
02493 
02494   return 0;
02495 
02496 }
02497 
02499 int fn_fsal_ln(int argc,        /* IN : number of args in argv */
02500                char **argv,     /* IN : arg list               */
02501                FILE * output    /* IN : output stream          */
02502     )
02503 {
02504 
02505   char format[] = "hv";
02506 
02507   const char help_ln[] =
02508       "ln: create a symbolic link.\n"
02509       "usage: ln [-h][-v] <link_content> <link_path>\n"
02510       "       link_content: content of the symbolic link to be created\n"
02511       "       link_path: path of the symbolic link to be created\n";
02512 
02513   char glob_path[FSAL_MAX_PATH_LEN];
02514   fsal_handle_t path_hdl, link_hdl;
02515   fsal_status_t st;
02516   int rc, option;
02517   int flag_v = 0;
02518   int flag_h = 0;
02519   int err_flag = 0;
02520 
02521   char *content = NULL;
02522   char tmp_path[FSAL_MAX_PATH_LEN];
02523   char *path;
02524   char *name;
02525 
02526   fsal_name_t objname;
02527   fsal_path_t objcontent;
02528 
02529   cmdfsal_thr_info_t *context;
02530 
02531   /* is the fs initialized ? */
02532   if(!is_loaded)
02533     {
02534       fprintf(output, "Error: filesystem not initialized\n");
02535       return -1;
02536     }
02537 
02538   /* initialize current thread */
02539 
02540   context = GetFSALCmdContext();
02541 
02542   if(context->is_thread_ok != TRUE)
02543     {
02544       int rc;
02545       rc = Init_Thread_Context(output, context, 0);
02546       if(rc != 0)
02547         return rc;
02548     }
02549 
02550   /* analysing options */
02551   getopt_init();
02552   while((option = Getopt(argc, argv, format)) != -1)
02553     {
02554       switch (option)
02555         {
02556         case 'v':
02557           if(flag_v)
02558             fprintf(output,
02559                     "ln: warning: option 'v' has been specified more than once.\n");
02560           else
02561             flag_v++;
02562           break;
02563         case 'h':
02564           if(flag_h)
02565             fprintf(output,
02566                     "ln: warning: option 'h' has been specified more than once.\n");
02567           else
02568             flag_h++;
02569           break;
02570         case '?':
02571           fprintf(output, "ln: unknown option : %c\n", Optopt);
02572           err_flag++;
02573           break;
02574         }
02575     }
02576 
02577   if(flag_h)
02578     {
02579       fprintf(output, help_ln);
02580       return 0;
02581     }
02582 
02583   /* 2 args expected */
02584 
02585   if(Optind == (argc - 2))
02586     {
02587 
02588       content = argv[Optind];
02589 
02590       strncpy(tmp_path, argv[Optind + 1], FSAL_MAX_PATH_LEN);
02591       split_path(tmp_path, &path, &name);
02592 
02593     }
02594   else
02595     {
02596       err_flag++;
02597     }
02598 
02599   if(err_flag)
02600     {
02601       fprintf(output, help_ln);
02602       return -1;
02603     }
02604 
02605   /* copy current path. */
02606   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
02607 
02608   /* retrieves path handle */
02609   if((rc =
02610      solvepath(glob_path, FSAL_MAX_PATH_LEN,
02611                path, context->current_dir, &path_hdl, output)))
02612     return rc;
02613 
02614   /* create fsal_name_t */
02615   st = FSAL_str2name(name, 256, &objname);
02616 
02617   if(FSAL_IS_ERROR(st))
02618     {
02619       fprintf(output, "Error executing FSAL_str2name:");
02620       print_fsal_status(output, st);
02621       fprintf(output, "\n");
02622       return st.major;
02623     }
02624 
02625   /* create fsal_path_t */
02626   st = FSAL_str2path(content, 256, &objcontent);
02627 
02628   if(FSAL_IS_ERROR(st))
02629     {
02630       fprintf(output, "Error executing FSAL_str2path:");
02631       print_fsal_status(output, st);
02632       fprintf(output, "\n");
02633       return st.major;
02634     }
02635 
02636   st = FSAL_symlink(&path_hdl,  /* IN - parent dir handle */
02637                     &objname,   /* IN - link name */
02638                     &objcontent,        /* IN - link content */
02639                     &context->context,  /* IN - user contexte */
02640                     0777,       /* IN (ignored) */
02641                     &link_hdl,  /* OUT - link handle */
02642                     NULL);      /* OUT - link attributes */
02643 
02644   if(FSAL_IS_ERROR(st))
02645     {
02646       fprintf(output, "Error executing FSAL_symlink:");
02647       print_fsal_status(output, st);
02648       fprintf(output, "\n");
02649       return st.major;
02650     }
02651 
02652   if(flag_v)
02653     {
02654       char buff[2 * sizeof(fsal_handle_t) + 1];
02655       snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &link_hdl);
02656 
02657       fprintf(output, "%s/%s -> %s successfully created (@%s) \n", path, name, content,
02658               buff);
02659 
02660     }
02661 
02662   return 0;
02663 
02664 }
02665 
02667 int fn_fsal_hardlink(int argc,  /* IN : number of args in argv */
02668                      char **argv,       /* IN : arg list               */
02669                      FILE * output      /* IN : output stream          */
02670     )
02671 {
02672 
02673   char format[] = "hv";
02674 
02675   const char help_hardlink[] =
02676       "hardlink: create a hard link.\n"
02677       "usage: hardlink [-h][-v] <target> <new_path>\n"
02678       "       target: path of an existing file.\n"
02679       "       new_path: path of the hardlink to be created\n";
02680 
02681   char glob_path_target[FSAL_MAX_PATH_LEN];
02682   char glob_path_link[FSAL_MAX_PATH_LEN];
02683 
02684   fsal_handle_t target_hdl, dir_hdl;
02685   fsal_name_t link_name;
02686 
02687   fsal_status_t st;
02688   int rc, option;
02689   int flag_v = 0;
02690   int flag_h = 0;
02691   int err_flag = 0;
02692 
02693   char *target = NULL;
02694 
02695   char tmp_path[FSAL_MAX_PATH_LEN];
02696   char *path;
02697   char *name;
02698 
02699   cmdfsal_thr_info_t *context;
02700 
02701   /* is the fs initialized ? */
02702   if(!is_loaded)
02703     {
02704       fprintf(output, "Error: filesystem not initialized\n");
02705       return -1;
02706     }
02707 
02708   /* initialize current thread */
02709 
02710   context = GetFSALCmdContext();
02711 
02712   if(context->is_thread_ok != TRUE)
02713     {
02714       int rc;
02715       rc = Init_Thread_Context(output, context, 0);
02716       if(rc != 0)
02717         return rc;
02718     }
02719 
02720   /* analysing options */
02721   getopt_init();
02722   while((option = Getopt(argc, argv, format)) != -1)
02723     {
02724       switch (option)
02725         {
02726         case 'v':
02727           if(flag_v)
02728             fprintf(output,
02729                     "hardlink: warning: option 'v' has been specified more than once.\n");
02730           else
02731             flag_v++;
02732           break;
02733         case 'h':
02734           if(flag_h)
02735             fprintf(output,
02736                     "hardlink: warning: option 'h' has been specified more than once.\n");
02737           else
02738             flag_h++;
02739           break;
02740         case '?':
02741           fprintf(output, "hardlink: unknown option : %c\n", Optopt);
02742           err_flag++;
02743           break;
02744         }
02745     }
02746 
02747   if(flag_h)
02748     {
02749       fprintf(output, help_hardlink);
02750       return 0;
02751     }
02752 
02753   /* 2 args expected */
02754 
02755   if(Optind == (argc - 2))
02756     {
02757 
02758       target = argv[Optind];
02759 
02760       strncpy(tmp_path, argv[Optind + 1], FSAL_MAX_PATH_LEN);
02761       split_path(tmp_path, &path, &name);
02762 
02763     }
02764   else
02765     {
02766       err_flag++;
02767     }
02768 
02769   if(err_flag)
02770     {
02771       fprintf(output, help_hardlink);
02772       return -1;
02773     }
02774 
02775   /* copy current path. */
02776   strncpy(glob_path_target, context->current_path, FSAL_MAX_PATH_LEN);
02777   strncpy(glob_path_link, context->current_path, FSAL_MAX_PATH_LEN);
02778 
02779   /* retrieves path handle for target */
02780   if((rc =
02781      solvepath(glob_path_target, FSAL_MAX_PATH_LEN,
02782                target, context->current_dir, &target_hdl, output)))
02783     return rc;
02784 
02785   /* retrieves path handle for parent dir */
02786   if((rc =
02787      solvepath(glob_path_link, FSAL_MAX_PATH_LEN,
02788                path, context->current_dir, &dir_hdl, output)))
02789     return rc;
02790 
02791   /* create fsal_name_t */
02792   st = FSAL_str2name(name, 256, &link_name);
02793 
02794   if(FSAL_IS_ERROR(st))
02795     {
02796       fprintf(output, "Error executing FSAL_str2name:");
02797       print_fsal_status(output, st);
02798       fprintf(output, "\n");
02799       return st.major;
02800     }
02801 
02802   st = FSAL_link(&target_hdl,   /* IN - target file */
02803                  &dir_hdl,      /* IN - parent dir handle */
02804                  &link_name,    /* IN - link name */
02805                  &context->context,     /* IN - user contexte */
02806                  NULL);         /* OUT - new attributes */
02807 
02808   if(FSAL_IS_ERROR(st))
02809     {
02810       fprintf(output, "Error executing FSAL_link:");
02811       print_fsal_status(output, st);
02812       fprintf(output, "\n");
02813       return st.major;
02814     }
02815 
02816   if(flag_v)
02817     {
02818       fprintf(output, "%s/%s <=> %s successfully created\n", path, name,
02819               glob_path_target);
02820 
02821     }
02822 
02823   return 0;
02824 
02825 }
02826 
02828 int fn_fsal_create(int argc,    /* IN : number of args in argv */
02829                    char **argv, /* IN : arg list               */
02830                    FILE * output        /* IN : output stream          */
02831     )
02832 {
02833 
02834   char format[] = "hv";
02835 
02836   const char help_create[] =
02837       "usage: create [-h][-v] <path> <mode>\n"
02838       "       path: path of the file to be created\n"
02839       "       mode: octal access mode for the file to be created (ex: 644)\n";
02840 
02841   char glob_path_dir[FSAL_MAX_PATH_LEN];
02842   fsal_handle_t dir_hdl, file_hdl;
02843 
02844   fsal_status_t st;
02845   int rc, option;
02846   int flag_v = 0;
02847   int flag_h = 0;
02848   int err_flag = 0;
02849   int mode;
02850   fsal_accessmode_t fsalmode = 0644;
02851 
02852   char tmp_path[FSAL_MAX_PATH_LEN];
02853   char *path;
02854   char *file;
02855   char *strmode;
02856 
02857   fsal_name_t objname;
02858 
02859   cmdfsal_thr_info_t *context;
02860 
02861   /* is the fs initialized ? */
02862   if(!is_loaded)
02863     {
02864       fprintf(output, "Error: filesystem not initialized\n");
02865       return -1;
02866     }
02867 
02868   /* initialize current thread */
02869 
02870   context = GetFSALCmdContext();
02871 
02872   if(context->is_thread_ok != TRUE)
02873     {
02874       int rc;
02875       rc = Init_Thread_Context(output, context, 0);
02876       if(rc != 0)
02877         return rc;
02878     }
02879 
02880   /* analysing options */
02881   getopt_init();
02882   while((option = Getopt(argc, argv, format)) != -1)
02883     {
02884       switch (option)
02885         {
02886         case 'v':
02887           if(flag_v)
02888             fprintf(output,
02889                     "create: warning: option 'v' has been specified more than once.\n");
02890           else
02891             flag_v++;
02892           break;
02893         case 'h':
02894           if(flag_h)
02895             fprintf(output,
02896                     "create: warning: option 'h' has been specified more than once.\n");
02897           else
02898             flag_h++;
02899           break;
02900         case '?':
02901           fprintf(output, "create: unknown option : %c\n", Optopt);
02902           err_flag++;
02903           break;
02904         }
02905     }
02906 
02907   if(flag_h)
02908     {
02909       fprintf(output, help_create);
02910       return 0;
02911     }
02912 
02913   /* Exactly 2 args expected */
02914   if(Optind != (argc - 2))
02915     {
02916       err_flag++;
02917     }
02918   else
02919     {
02920 
02921       strncpy(tmp_path, argv[Optind], FSAL_MAX_PATH_LEN);
02922       split_path(tmp_path, &path, &file);
02923 
02924       strmode = argv[Optind + 1];
02925 
02926       /* converting mode string to FSAL mode string */
02927       mode = atomode(strmode);
02928       if(mode < 0)
02929         err_flag++;
02930       else
02931         {
02932 
02933           fsalmode = 0;
02934 
02935           if(mode & S_ISUID)
02936             fsalmode |= FSAL_MODE_SUID;
02937           if(mode & S_ISGID)
02938             fsalmode |= FSAL_MODE_SGID;
02939 
02940           if(mode & S_IRUSR)
02941             fsalmode |= FSAL_MODE_RUSR;
02942           if(mode & S_IWUSR)
02943             fsalmode |= FSAL_MODE_WUSR;
02944           if(mode & S_IXUSR)
02945             fsalmode |= FSAL_MODE_XUSR;
02946 
02947           if(mode & S_IRGRP)
02948             fsalmode |= FSAL_MODE_RGRP;
02949           if(mode & S_IWGRP)
02950             fsalmode |= FSAL_MODE_WGRP;
02951           if(mode & S_IXGRP)
02952             fsalmode |= FSAL_MODE_XGRP;
02953 
02954           if(mode & S_IROTH)
02955             fsalmode |= FSAL_MODE_ROTH;
02956           if(mode & S_IWOTH)
02957             fsalmode |= FSAL_MODE_WOTH;
02958           if(mode & S_IXOTH)
02959             fsalmode |= FSAL_MODE_XOTH;
02960 
02961         }
02962 
02963     }
02964 
02965   if(err_flag)
02966     {
02967       fprintf(output, help_create);
02968       return -1;
02969     }
02970 
02971   /* copy current path. */
02972   strncpy(glob_path_dir, context->current_path, FSAL_MAX_PATH_LEN);
02973 
02974   /* retrieves path handle */
02975   if((rc =
02976      solvepath(glob_path_dir, FSAL_MAX_PATH_LEN,
02977                path, context->current_dir, &dir_hdl, output)))
02978     return rc;
02979 
02980   /* create fsal_name_t */
02981   st = FSAL_str2name(file, 256, &objname);
02982   if(FSAL_IS_ERROR(st))
02983     {
02984       fprintf(output, "Error executing FSAL_str2name:");
02985       print_fsal_status(output, st);
02986       fprintf(output, "\n");
02987       return st.major;
02988     }
02989 
02990   st = FSAL_create(&dir_hdl,    /* IN */
02991                    &objname,    /* IN */
02992                    &context->context,   /* IN */
02993                    fsalmode,    /* IN */
02994                    &file_hdl,   /* OUT */
02995                    /*&context->current_fd, *//* OUT */
02996                    NULL         /* [ IN/OUT ] */
02997       );
02998 
02999   if(FSAL_IS_ERROR(st))
03000     {
03001       fprintf(output, "Error executing FSAL_create:");
03002       print_fsal_status(output, st);
03003       fprintf(output, "\n");
03004       return st.major;
03005     }
03006 
03007   if(flag_v)
03008     {
03009       char buff[2 * sizeof(fsal_handle_t) + 1];
03010       snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &file_hdl);
03011 
03012       fprintf(output, "%s/%s successfully created (@%s) \n", glob_path_dir, file, buff);
03013 
03014     }
03015 
03016   return 0;
03017 
03018 }
03019 
03020 /* setattr
03021  *
03022  * syntax of command line:
03023  * setattr file_path  attribute_name  attribute_value
03024  *
03025  */
03026 int fn_fsal_setattr(int argc,   /* IN : number of args in argv */
03027                     char **argv,        /* IN : arg list               */
03028                     FILE * output       /* IN : output stream          */
03029     )
03030 {
03031 
03032   char format[] = "hv";
03033 
03034   const char help_setattr[] =
03035       "usage: setattr [-h][-v] <path> <attr>=<value>,<attr>=<value>,...\n";
03036 
03037   char glob_path[FSAL_MAX_PATH_LEN];    /* absolute path of the object */
03038   fsal_handle_t obj_hdl;        /* handle of the object */
03039   fsal_attrib_list_t set_attrs; /* attributes to be setted */
03040   fsal_status_t st;             /* FSAL return status */
03041 
03042   int rc, option;
03043   int flag_v = 0;
03044   int flag_h = 0;
03045   int err_flag = 0;
03046 
03047   char *file = NULL;            /* the relative path to the object */
03048   char *attr_list = NULL;       /* attribute list */
03049 
03050   cmdfsal_thr_info_t *context;
03051 
03052   /* is the fs initialized ? */
03053   if(!is_loaded)
03054     {
03055       fprintf(output, "Error: filesystem not initialized\n");
03056       return -1;
03057     }
03058 
03059   /* initialize current thread */
03060 
03061   context = GetFSALCmdContext();
03062 
03063   if(context->is_thread_ok != TRUE)
03064     {
03065       int rc;
03066       rc = Init_Thread_Context(output, context, 0);
03067       if(rc != 0)
03068         return rc;
03069     }
03070 
03071   /* analysing options */
03072 
03073   getopt_init();
03074   while((option = Getopt(argc, argv, format)) != -1)
03075     {
03076       switch (option)
03077         {
03078 
03079         case 'v':
03080           if(flag_v)
03081             fprintf(output,
03082                     "setattr: warning: option 'v' has been specified more than once.\n");
03083           else
03084             flag_v++;
03085           break;
03086 
03087         case 'h':
03088           if(flag_h)
03089             fprintf(output,
03090                     "setattr: warning: option 'h' has been specified more than once.\n");
03091           else
03092             flag_h++;
03093           break;
03094 
03095         case '?':
03096           fprintf(output, "setattr: unknown option : %c\n", Optopt);
03097           err_flag++;
03098           break;
03099         }
03100     }
03101 
03102   if(flag_h)
03103     {
03104 
03105       shell_attribute_t *curr_attr;
03106 
03107       /* print usage */
03108       fprintf(output, help_setattr);
03109 
03110       fprintf(output, "\n<attr> can be one of the following values:\n");
03111 
03112       /* print attribute list */
03113 
03114       for(curr_attr = shell_attr_list; curr_attr->attr_type != ATTR_NONE; curr_attr++)
03115         {
03116           switch (curr_attr->attr_type)
03117             {
03118             case ATTR_32:
03119               fprintf(output, "\t %s \t:\t 32 bits integer\n", curr_attr->attr_name);
03120               break;
03121             case ATTR_64:
03122               fprintf(output, "\t %s \t:\t 64 bits integer\n", curr_attr->attr_name);
03123               break;
03124             case ATTR_OCTAL:
03125               fprintf(output, "\t %s \t:\t octal\n", curr_attr->attr_name);
03126               break;
03127             case ATTR_TIME:
03128               fprintf(output, "\t %s \t:\t time (format: YYYYMMDDhhmmss)\n",
03129                       curr_attr->attr_name);
03130               break;
03131             default:
03132               break;
03133             }
03134         }
03135 
03136       return 0;
03137     }
03138 
03139   /* Exactly 2 args expected (path and attributes) */
03140 
03141   if(Optind != (argc - 2))
03142     {
03143       err_flag++;
03144     }
03145   else
03146     {
03147       file = argv[Optind];
03148       attr_list = argv[Optind + 1];
03149     }
03150 
03151   if(err_flag)
03152     {
03153       fprintf(output, help_setattr);
03154       return -1;
03155     }
03156 
03157   /* copy current absolute path to a local variable. */
03158 
03159   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
03160 
03161   /* retrieve handle to the file whose attributes are to be changed */
03162 
03163   rc = solvepath(glob_path, FSAL_MAX_PATH_LEN, file, context->current_dir,
03164                  &obj_hdl, output);
03165   if(rc)
03166     return rc;
03167 
03168   /* Convert the peers (attr_name,attr_val) to an FSAL attribute structure. */
03169   rc = MkFSALSetAttrStruct(attr_list, &set_attrs);
03170 
03171   /* interprets output code */
03172   switch (rc)
03173     {
03174     case 0:
03175       /* OK */
03176       break;
03177 
03178     case EFAULT:
03179       fprintf(output, "setattr: Internal error.\n");
03180       return rc;
03181 
03182     case ENOENT:
03183       fprintf(output, "setattr: Unknown attribute in list %s\n", attr_list);
03184       return rc;
03185 
03186     case EINVAL:
03187       fprintf(output, "setattr: Invalid value for attribute in list %s\n", attr_list);
03188       return rc;
03189 
03190     default:
03191       fprintf(output, "setattr: Error %d converting attributes.\n", rc);
03192       return rc;
03193     }
03194 
03195   /* if verbose mode is on, we print the attributes to be set */
03196   if(flag_v)
03197     {
03198       print_fsal_attributes(set_attrs, output);
03199     }
03200 
03201   /* executes set attrs */
03202 
03203   st = FSAL_setattrs(&obj_hdl, &context->context, &set_attrs, NULL);
03204 
03205   if(FSAL_IS_ERROR(st))
03206     {
03207       fprintf(output, "Error executing FSAL_setattrs:");
03208       print_fsal_status(output, st);
03209       fprintf(output, "\n");
03210       return st.major;
03211     }
03212 
03213   return 0;
03214 
03215 }
03216 
03223 int fn_fsal_access(int argc,    /* IN : number of args in argv */
03224                    char **argv, /* IN : arg list               */
03225                    FILE * output        /* IN : output stream          */
03226     )
03227 {
03228 
03229   char format[] = "hvA";
03230 
03231   const char help_access[] =
03232       "usage: access [-h][-v][-A] <rights> <path>\n"
03233       "\n"
03234       "   -h : print this help\n"
03235       "   -v : verbose mode\n"
03236       "   -A : test access from attributes\n"
03237       "        ( call to getattr + test_access instead of access )\n"
03238       "\n"
03239       " <rights> : a set of the following characters:\n"
03240       "    F: test file existence\n"
03241       "    R: test read permission\n"
03242       "    W: test write permission\n"
03243       "    X: test execute permission\n"
03244       "\n"
03245       "Example: access -A RX my_dir\n"
03246       "test read and exec rights for directory \"my_dir\"\n"
03247       "by doing a getattr and a test_access call.\n\n";
03248 
03249   char glob_path[FSAL_MAX_PATH_LEN];    /* absolute path of the object */
03250   fsal_handle_t obj_hdl;        /* handle of the object */
03251   fsal_accessflags_t test_perms;        /* permissions to be tested */
03252   fsal_status_t st;             /* FSAL return status */
03253 
03254   int rc, option;
03255   unsigned int i;
03256   int flag_v = 0;
03257   int flag_h = 0;
03258   int flag_A = 0;
03259   int err_flag = 0;
03260 
03261   char *file = NULL;            /* the relative path to the object */
03262   char *str_perms = NULL;       /* string that represents the permissions to be tested */
03263 
03264   cmdfsal_thr_info_t *context;
03265 
03266   /* is the fs initialized ? */
03267   if(!is_loaded)
03268     {
03269       fprintf(output, "Error: filesystem not initialized\n");
03270       return -1;
03271     }
03272 
03273   /* initialize current thread */
03274 
03275   context = GetFSALCmdContext();
03276 
03277   if(context->is_thread_ok != TRUE)
03278     {
03279       int rc;
03280       rc = Init_Thread_Context(output, context, 0);
03281       if(rc != 0)
03282         return rc;
03283     }
03284 
03285   /* analysing options */
03286 
03287   getopt_init();
03288   while((option = Getopt(argc, argv, format)) != -1)
03289     {
03290       switch (option)
03291         {
03292 
03293         case 'v':
03294           if(flag_v)
03295             fprintf(output,
03296                     "access: warning: option 'v' has been specified more than once.\n");
03297           else
03298             flag_v++;
03299           break;
03300 
03301         case 'h':
03302           if(flag_h)
03303             fprintf(output,
03304                     "access: warning: option 'h' has been specified more than once.\n");
03305           else
03306             flag_h++;
03307           break;
03308 
03309         case 'A':
03310           if(flag_A)
03311             fprintf(output,
03312                     "access: warning: option 'A' has been specified more than once.\n");
03313           else
03314             flag_A++;
03315           break;
03316 
03317         case '?':
03318           fprintf(output, "access: unknown option : %c\n", Optopt);
03319           err_flag++;
03320           break;
03321         }
03322     }
03323 
03324   if(flag_h)
03325     {
03326 
03327       /* print usage */
03328       fprintf(output, help_access);
03329       return 0;
03330 
03331     }
03332 
03333   /* Exactly 2 args expected */
03334 
03335   if(Optind != (argc - 2))
03336     {
03337       err_flag++;
03338     }
03339   else
03340     {
03341       str_perms = argv[Optind];
03342       file = argv[Optind + 1];
03343     }
03344 
03345   if(err_flag)
03346     {
03347       fprintf(output, help_access);
03348       return -1;
03349     }
03350 
03351   /* copy current absolute path to a local variable. */
03352 
03353   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
03354 
03355   /* retrieve handle to the file whose permissions are to be tested */
03356 
03357   rc = solvepath(glob_path, FSAL_MAX_PATH_LEN, file, context->current_dir, &obj_hdl,
03358                  output);
03359   if(rc)
03360     return rc;
03361 
03362   /* Convert the permission string to an fsal access test. */
03363 
03364   test_perms = 0;
03365 
03366   for(i = 0; i < strlen(str_perms); i++)
03367     {
03368       switch (str_perms[i])
03369         {
03370         case 'F':
03371           if(flag_v)
03372             fprintf(output, "F_OK flag\n");
03373           test_perms |= FSAL_F_OK;
03374           break;
03375 
03376         case 'R':
03377           if(flag_v)
03378             fprintf(output, "R_OK flag\n");
03379           test_perms |= FSAL_R_OK;
03380           break;
03381 
03382         case 'W':
03383           if(flag_v)
03384             fprintf(output, "W_OK flag\n");
03385           test_perms |= FSAL_W_OK;
03386           break;
03387 
03388         case 'X':
03389           if(flag_v)
03390             fprintf(output, "X_OK flag\n");
03391           test_perms |= FSAL_X_OK;
03392           break;
03393 
03394         default:
03395           fprintf(output, "**** Invalid test: %c ****\n", str_perms[i]);
03396           fprintf(output, help_access);
03397           return -1;
03398         }
03399     }
03400 
03401   /* Call to FSAL */
03402 
03403   if(flag_A)
03404     {
03405       fsal_attrib_list_t attributes;
03406 
03407       /* 1st method: get attr and test_access */
03408 
03409       FSAL_CLEAR_MASK(attributes.asked_attributes);
03410       FSAL_SET_MASK(attributes.asked_attributes,
03411                     FSAL_ATTR_MODE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL);
03412 
03413       if(flag_v)
03414         fprintf(output, "Getting file attributes...\n");
03415 
03416       st = FSAL_getattrs(&obj_hdl, &context->context, &attributes);
03417 
03418       if(FSAL_IS_ERROR(st))
03419         {
03420           fprintf(output, "Error executing FSAL_getattrs:");
03421           print_fsal_status(output, st);
03422           fprintf(output, "\n");
03423           return st.major;
03424         }
03425 
03426       if(flag_v)
03427         {
03428           print_fsal_attributes(attributes, output);
03429         }
03430 
03431       if(flag_v)
03432         fprintf(output, "Testing access rights...\n");
03433 
03434       st = FSAL_test_access(&context->context, test_perms, &attributes);
03435 
03436       if(FSAL_IS_ERROR(st))
03437         {
03438 
03439           fprintf(output, "Error executing FSAL_test_access:");
03440           print_fsal_status(output, st);
03441           fprintf(output, "\n");
03442           return st.major;
03443 
03444         }
03445       else
03446         {
03447 
03448           fprintf(output, "access: Access granted.\n");
03449           return 0;
03450 
03451         }
03452 
03453     }
03454   else
03455     {
03456       /* 2nd method: simply calling access */
03457 
03458       if(flag_v)
03459         fprintf(output, "Calling access\n");
03460 
03461       st = FSAL_access(&obj_hdl, &context->context, test_perms, NULL);
03462 
03463       if(FSAL_IS_ERROR(st))
03464         {
03465 
03466           fprintf(output, "Error executing FSAL_access:");
03467           print_fsal_status(output, st);
03468           fprintf(output, "\n");
03469           return st.major;
03470 
03471         }
03472       else
03473         {
03474 
03475           fprintf(output, "access: Access granted.\n");
03476           return 0;
03477         }
03478 
03479     }
03480 
03481 }
03482 
03484 int fn_fsal_truncate(int argc,  /* IN : number of args in argv */
03485                      char **argv,       /* IN : arg list               */
03486                      FILE * output      /* IN : output stream          */
03487     )
03488 {
03489 
03490   char format[] = "hv";
03491 
03492   const char help_truncate[] = "usage: truncate [-h][-v] <file> <size>\n";
03493 
03494   char glob_path[FSAL_MAX_PATH_LEN];
03495   fsal_handle_t filehdl;
03496 
03497   fsal_status_t st;
03498   fsal_size_t trunc_size;
03499 
03500   int rc, option;
03501   int flag_v = 0;
03502   int flag_h = 0;
03503   int err_flag = 0;
03504 
03505   char *file = NULL;
03506   char *str_size = NULL;
03507 
03508   cmdfsal_thr_info_t *context;
03509 
03510   /* is the fs initialized ? */
03511   if(!is_loaded)
03512     {
03513       fprintf(output, "Error: filesystem not initialized\n");
03514       return -1;
03515     }
03516 
03517   /* initialize current thread */
03518 
03519   context = GetFSALCmdContext();
03520 
03521   if(context->is_thread_ok != TRUE)
03522     {
03523       int rc;
03524       rc = Init_Thread_Context(output, context, 0);
03525       if(rc != 0)
03526         return rc;
03527     }
03528 
03529   /* analysing options */
03530   getopt_init();
03531   while((option = Getopt(argc, argv, format)) != -1)
03532     {
03533       switch (option)
03534         {
03535         case 'v':
03536           if(flag_v)
03537             fprintf(output,
03538                     "truncate: warning: option 'v' has been specified more than once.\n");
03539           else
03540             flag_v++;
03541           break;
03542         case 'h':
03543           if(flag_h)
03544             fprintf(output,
03545                     "truncate: warning: option 'h' has been specified more than once.\n");
03546           else
03547             flag_h++;
03548           break;
03549         case '?':
03550           fprintf(output, "truncate: unknown option : %c\n", Optopt);
03551           err_flag++;
03552           break;
03553         }
03554     }
03555 
03556   if(flag_h)
03557     {
03558       fprintf(output, help_truncate);
03559       return 0;
03560     }
03561 
03562   /* Exactly two arg expected */
03563   if(Optind != (argc - 2))
03564     {
03565       err_flag++;
03566     }
03567   else
03568     {
03569       file = argv[Optind];
03570       str_size = argv[Optind + 1];
03571 
03572       rc = ato64(str_size, &trunc_size);
03573       if(rc == -1)
03574         {
03575           fprintf(output, "truncate: error: invalid trunc size \"%s\"\n", str_size);
03576           err_flag++;
03577         }
03578 
03579     }
03580 
03581   if(err_flag)
03582     {
03583       fprintf(output, help_truncate);
03584       return -1;
03585     }
03586 
03587   /* copy current path. */
03588   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
03589 
03590   /* retrieves object handle */
03591   if((rc =
03592      solvepath(glob_path, FSAL_MAX_PATH_LEN,
03593                file, context->current_dir, &filehdl, output)))
03594     return rc;
03595 
03596   if(flag_v)
03597     fprintf(output, "Truncating \"%s\" to %llu bytes.\n", glob_path, trunc_size);
03598 
03599   st = FSAL_truncate(&filehdl, &context->context, trunc_size, NULL,     /* Will fail with FSAL_PROXY */
03600                      NULL);
03601 
03602   if(FSAL_IS_ERROR(st))
03603     {
03604       fprintf(output, "Error executing FSAL_truncate:");
03605       print_fsal_status(output, st);
03606       fprintf(output, "\n");
03607       return st.major;
03608     }
03609 
03610   if(flag_v)
03611     fprintf(output, "Truncate operation completed sucessfully.\n");
03612 
03613   return 0;
03614 
03615 }
03616 
03621 int fn_fsal_open_byname(int argc,       /* IN : number of args in argv */
03622                         char **argv,    /* IN : arg list               */
03623                         FILE * output   /* IN : output stream          */
03624     )
03625 {
03626 
03627   char format[] = "hv";
03628 
03629   const char help_open[] =
03630       "usage: open_byname [-h][-v] <path> [<oflags>]\n"
03631       "   where <oflags> is a set of the following values:\n"
03632       "   'r': read, 'w': write, 'a': append, 't': truncate.\n";
03633 
03634   char glob_path[FSAL_MAX_PATH_LEN];
03635   fsal_name_t filename;
03636 
03637   fsal_status_t st;
03638 
03639   int option;
03640   int flag_v = 0;
03641   int flag_h = 0;
03642   int err_flag = 0;
03643 
03644   fsal_openflags_t o_flags;
03645 
03646   int flag_r = 0;
03647   int flag_w = 0;
03648   int flag_a = 0;
03649   int flag_t = 0;
03650 
03651   char *file = NULL;
03652   char *opt_str;
03653 
03654   cmdfsal_thr_info_t *context;
03655 
03656   /* is the fs initialized ? */
03657   if(!is_loaded)
03658     {
03659       fprintf(output, "Error: filesystem not initialized\n");
03660       return -1;
03661     }
03662 
03663   /* initialize current thread */
03664 
03665   context = GetFSALCmdContext();
03666 
03667   if(context->is_thread_ok != TRUE)
03668     {
03669       int rc;
03670       rc = Init_Thread_Context(output, context, 0);
03671       if(rc != 0)
03672         return rc;
03673     }
03674 
03675   /* is a file already opened ? */
03676   if(context->opened)
03677     {
03678       fprintf(output, "Error: a file is already opened. Use 'close' command first.\n");
03679       return -1;
03680     }
03681 
03682   /* analysing options */
03683 
03684   getopt_init();
03685   while((option = Getopt(argc, argv, format)) != -1)
03686     {
03687       switch (option)
03688         {
03689         case 'v':
03690           if(flag_v)
03691             fprintf(output,
03692                     "open: warning: option 'v' has been specified more than once.\n");
03693           else
03694             flag_v++;
03695           break;
03696         case 'h':
03697           if(flag_h)
03698             fprintf(output,
03699                     "open: warning: option 'h' has been specified more than once.\n");
03700           else
03701             flag_h++;
03702           break;
03703         case '?':
03704           fprintf(output, "open: unknown option : %c\n", Optopt);
03705           err_flag++;
03706           break;
03707         }
03708     }
03709 
03710   if(flag_h)
03711     {
03712       fprintf(output, help_open);
03713       return 0;
03714     }
03715 
03716   /* one or two args expected */
03717   if(Optind > (argc - 1))
03718     err_flag++;
03719   else
03720     {
03721       file = argv[Optind];
03722 
03723       Optind++;
03724 
03725       /* optional flags */
03726       while(Optind < argc)
03727         {
03728           /* test flags */
03729           opt_str = argv[Optind];
03730 
03731           while(*opt_str)
03732             {
03733               switch (*opt_str)
03734                 {
03735                 case 'r':
03736                 case 'R':
03737                   flag_r++;
03738                   break;
03739 
03740                 case 'w':
03741                 case 'W':
03742                   flag_w++;
03743                   break;
03744 
03745                 case 'a':
03746                 case 'A':
03747                   flag_a++;
03748                   break;
03749 
03750                 case 't':
03751                 case 'T':
03752                   flag_t++;
03753                   break;
03754 
03755                 default:
03756                   fprintf(output, "open_byname: unknown open flag : '%c'\n", *opt_str);
03757                   err_flag++;
03758                 }
03759               opt_str++;
03760             }
03761 
03762           Optind++;
03763         }
03764 
03765     }
03766 
03767   if(err_flag)
03768     {
03769       fprintf(output, help_open);
03770       return -1;
03771     }
03772 
03773   /* Convert filename to fsal_name_t */
03774   if(FSAL_IS_ERROR(st = FSAL_str2name(file, FSAL_MAX_PATH_LEN, &filename)))
03775     {
03776       fprintf(output, "Error executing FSAL_str2name:");
03777       print_fsal_status(output, st);
03778       fprintf(output, "\n");
03779       return st.major;
03780     }
03781 
03782   /* make open flags */
03783 
03784   o_flags = 0;
03785 
03786   if(flag_r && flag_w)
03787     o_flags |= FSAL_O_RDWR;
03788   else if(flag_r)
03789     o_flags |= FSAL_O_RDONLY;
03790   else if(flag_w)
03791     o_flags |= FSAL_O_WRONLY;
03792 
03793   if(flag_a)
03794     o_flags |= FSAL_O_APPEND;
03795   if(flag_t)
03796     o_flags |= FSAL_O_TRUNC;
03797 
03798   if(flag_v)
03799     fprintf(output, "Open operation on %s with flags %#X.\n", glob_path, o_flags);
03800 
03801   st = FSAL_open_by_name(&(context->current_dir), &filename, &context->context, o_flags,
03802                          &context->current_fd, NULL);
03803 
03804   if(FSAL_IS_ERROR(st))
03805     {
03806       fprintf(output, "Error executing FSAL_open:");
03807       print_fsal_status(output, st);
03808       fprintf(output, "\n");
03809       return st.major;
03810     }
03811 
03812   /* note that a file is opened. */
03813   context->opened = TRUE;
03814 
03815   if(flag_v)
03816     fprintf(output, "Open operation completed sucessfully : fd = %d.\n",
03817             FSAL_FILENO(&(context->current_fd)));
03818 
03819   return 0;
03820 
03821 }
03822 
03827 int fn_fsal_open(int argc,      /* IN : number of args in argv */
03828                  char **argv,   /* IN : arg list               */
03829                  FILE * output  /* IN : output stream          */
03830     )
03831 {
03832 
03833   char format[] = "hv";
03834 
03835   const char help_open[] =
03836       "usage: open [-h][-v] <path> [<oflags>]\n"
03837       "   where <oflags> is a set of the following values:\n"
03838       "   'r': read, 'w': write, 'a': append, 't': truncate.\n";
03839 
03840   char glob_path[FSAL_MAX_PATH_LEN];
03841   fsal_handle_t filehdl;
03842 
03843   fsal_status_t st;
03844 
03845   int rc, option;
03846   int flag_v = 0;
03847   int flag_h = 0;
03848   int err_flag = 0;
03849 
03850   fsal_openflags_t o_flags;
03851 
03852   int flag_r = 0;
03853   int flag_w = 0;
03854   int flag_a = 0;
03855   int flag_t = 0;
03856 
03857   char *file = NULL;
03858   char *opt_str;
03859 
03860   cmdfsal_thr_info_t *context;
03861 
03862   /* is the fs initialized ? */
03863   if(!is_loaded)
03864     {
03865       fprintf(output, "Error: filesystem not initialized\n");
03866       return -1;
03867     }
03868 
03869   /* initialize current thread */
03870 
03871   context = GetFSALCmdContext();
03872 
03873   if(context->is_thread_ok != TRUE)
03874     {
03875       int rc;
03876       rc = Init_Thread_Context(output, context, 0);
03877       if(rc != 0)
03878         return rc;
03879     }
03880 
03881   /* is a file already opened ? */
03882   if(context->opened)
03883     {
03884       fprintf(output, "Error: a file is already opened. Use 'close' command first.\n");
03885       return -1;
03886     }
03887 
03888   /* analysing options */
03889 
03890   getopt_init();
03891   while((option = Getopt(argc, argv, format)) != -1)
03892     {
03893       switch (option)
03894         {
03895         case 'v':
03896           if(flag_v)
03897             fprintf(output,
03898                     "open: warning: option 'v' has been specified more than once.\n");
03899           else
03900             flag_v++;
03901           break;
03902         case 'h':
03903           if(flag_h)
03904             fprintf(output,
03905                     "open: warning: option 'h' has been specified more than once.\n");
03906           else
03907             flag_h++;
03908           break;
03909         case '?':
03910           fprintf(output, "open: unknown option : %c\n", Optopt);
03911           err_flag++;
03912           break;
03913         }
03914     }
03915 
03916   if(flag_h)
03917     {
03918       fprintf(output, help_open);
03919       return 0;
03920     }
03921 
03922   /* one or two args expected */
03923   if(Optind > (argc - 1))
03924     err_flag++;
03925   else
03926     {
03927       file = argv[Optind];
03928 
03929       Optind++;
03930 
03931       /* optional flags */
03932       while(Optind < argc)
03933         {
03934           /* test flags */
03935           opt_str = argv[Optind];
03936 
03937           while(*opt_str)
03938             {
03939               switch (*opt_str)
03940                 {
03941                 case 'r':
03942                 case 'R':
03943                   flag_r++;
03944                   break;
03945 
03946                 case 'w':
03947                 case 'W':
03948                   flag_w++;
03949                   break;
03950 
03951                 case 'a':
03952                 case 'A':
03953                   flag_a++;
03954                   break;
03955 
03956                 case 't':
03957                 case 'T':
03958                   flag_t++;
03959                   break;
03960 
03961                 default:
03962                   fprintf(output, "open: unknown open flag : '%c'\n", *opt_str);
03963                   err_flag++;
03964                 }
03965               opt_str++;
03966             }
03967 
03968           Optind++;
03969         }
03970 
03971     }
03972 
03973   if(err_flag)
03974     {
03975       fprintf(output, help_open);
03976       return -1;
03977     }
03978 
03979   /* copy current path. */
03980   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
03981 
03982   /* retrieves object handle */
03983   if((rc =
03984      solvepath(glob_path, FSAL_MAX_PATH_LEN,
03985                file, context->current_dir, &filehdl, output)))
03986     return rc;
03987 
03988   /* make open flags */
03989 
03990   o_flags = 0;
03991 
03992   if(flag_r && flag_w)
03993     o_flags |= FSAL_O_RDWR;
03994   else if(flag_r)
03995     o_flags |= FSAL_O_RDONLY;
03996   else if(flag_w)
03997     o_flags |= FSAL_O_WRONLY;
03998 
03999   if(flag_a)
04000     o_flags |= FSAL_O_APPEND;
04001   if(flag_t)
04002     o_flags |= FSAL_O_TRUNC;
04003 
04004   if(flag_v)
04005     fprintf(output, "Open operation on %s with flags %#X.\n", glob_path, o_flags);
04006 
04007   st = FSAL_open(&filehdl, &context->context, o_flags, &context->current_fd, NULL);
04008 
04009   if(FSAL_IS_ERROR(st))
04010     {
04011       fprintf(output, "Error executing FSAL_open:");
04012       print_fsal_status(output, st);
04013       fprintf(output, "\n");
04014       return st.major;
04015     }
04016 
04017   /* note that a file is opened. */
04018   context->opened = TRUE;
04019 
04020   if(flag_v)
04021     fprintf(output, "Open operation completed sucessfully : fd = %d.\n",
04022             FSAL_FILENO(&(context->current_fd)));
04023 
04024   return 0;
04025 
04026 }
04027 
04032 int fn_fsal_open_byfileid(int argc,     /* IN : number of args in argv */
04033                           char **argv,  /* IN : arg list               */
04034                           FILE * output /* IN : output stream          */
04035     )
04036 {
04037 
04038   char format[] = "hv";
04039 
04040   const char help_open_byfileid[] =
04041       "usage: open_byfileid [-h][-v] <path> <fileid> [<oflags>]\n"
04042       "   where <oflags> is a set of the following values:\n"
04043       "   'r': read, 'w': write, 'a': append, 't': truncate.\n";
04044 
04045   char glob_path[FSAL_MAX_PATH_LEN];
04046   fsal_handle_t filehdl;
04047 
04048   fsal_status_t st;
04049 
04050   int rc, option;
04051   int flag_v = 0;
04052   int flag_h = 0;
04053   int err_flag = 0;
04054 
04055   fsal_openflags_t o_flags;
04056 
04057   int flag_r = 0;
04058   int flag_w = 0;
04059   int flag_a = 0;
04060   int flag_t = 0;
04061 
04062   char *file = NULL;
04063   char *strfileid = NULL;
04064   fsal_u64_t fileid = 0LL;
04065   char *opt_str;
04066 
04067   cmdfsal_thr_info_t *context;
04068 
04069   /* is the fs initialized ? */
04070   if(!is_loaded)
04071     {
04072       fprintf(output, "Error: filesystem not initialized\n");
04073       return -1;
04074     }
04075 
04076   /* initialize current thread */
04077 
04078   context = GetFSALCmdContext();
04079 
04080   if(context->is_thread_ok != TRUE)
04081     {
04082       int rc;
04083       rc = Init_Thread_Context(output, context, 0);
04084       if(rc != 0)
04085         return rc;
04086     }
04087 
04088   /* is a file already opened ? */
04089   if(context->opened)
04090     {
04091       fprintf(output, "Error: a file is already opened. Use 'close' command first.\n");
04092       return -1;
04093     }
04094 
04095   /* analysing options */
04096 
04097   getopt_init();
04098   while((option = Getopt(argc, argv, format)) != -1)
04099     {
04100       switch (option)
04101         {
04102         case 'v':
04103           if(flag_v)
04104             fprintf(output,
04105                     "open: warning: option 'v' has been specified more than once.\n");
04106           else
04107             flag_v++;
04108           break;
04109         case 'h':
04110           if(flag_h)
04111             fprintf(output,
04112                     "open: warning: option 'h' has been specified more than once.\n");
04113           else
04114             flag_h++;
04115           break;
04116         case '?':
04117           fprintf(output, "open: unknown option : %c\n", Optopt);
04118           err_flag++;
04119           break;
04120         }
04121     }
04122 
04123   if(flag_h)
04124     {
04125       fprintf(output, help_open_byfileid);
04126       return 0;
04127     }
04128 
04129   /* two or three args expected */
04130   if(Optind > (argc - 2))
04131     err_flag++;
04132   else
04133     {
04134       file = argv[Optind];
04135       strfileid = argv[Optind + 1];
04136       sscanf(strfileid, "%llu", &fileid);
04137 
04138       Optind += 2;
04139 
04140       /* optional flags */
04141       while(Optind < argc)
04142         {
04143           /* test flags */
04144           opt_str = argv[Optind];
04145 
04146           while(*opt_str)
04147             {
04148               switch (*opt_str)
04149                 {
04150                 case 'r':
04151                 case 'R':
04152                   flag_r++;
04153                   break;
04154 
04155                 case 'w':
04156                 case 'W':
04157                   flag_w++;
04158                   break;
04159 
04160                 case 'a':
04161                 case 'A':
04162                   flag_a++;
04163                   break;
04164 
04165                 case 't':
04166                 case 'T':
04167                   flag_t++;
04168                   break;
04169 
04170                 default:
04171                   fprintf(output, "open: unknown open flag : '%c'\n", *opt_str);
04172                   err_flag++;
04173                 }
04174               opt_str++;
04175             }
04176 
04177           Optind++;
04178         }
04179 
04180     }
04181 
04182   if(err_flag)
04183     {
04184       fprintf(output, help_open_byfileid);
04185       return -1;
04186     }
04187 
04188   /* copy current path. */
04189   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
04190 
04191   /* retrieves object handle */
04192   if((rc =
04193      solvepath(glob_path, FSAL_MAX_PATH_LEN,
04194                file, context->current_dir, &filehdl, output)))
04195     return rc;
04196 
04197   /* make open flags */
04198 
04199   o_flags = 0;
04200 
04201   if(flag_r && flag_w)
04202     o_flags |= FSAL_O_RDWR;
04203   else if(flag_r)
04204     o_flags |= FSAL_O_RDONLY;
04205   else if(flag_w)
04206     o_flags |= FSAL_O_WRONLY;
04207 
04208   if(flag_a)
04209     o_flags |= FSAL_O_APPEND;
04210   if(flag_t)
04211     o_flags |= FSAL_O_TRUNC;
04212 
04213   if(flag_v)
04214     fprintf(output, "Open operation on %s with flags %#X.\n", glob_path, o_flags);
04215 
04216   st = FSAL_open_by_fileid(&filehdl, fileid, &context->context, o_flags,
04217                            &context->current_fd, NULL);
04218 
04219   if(FSAL_IS_ERROR(st))
04220     {
04221       fprintf(output, "Error executing FSAL_open:");
04222       print_fsal_status(output, st);
04223       fprintf(output, "\n");
04224       return st.major;
04225     }
04226 
04227   /* note that a file is opened. */
04228   context->opened = TRUE;
04229 
04230   if(flag_v)
04231     fprintf(output, "Open operation completed sucessfully : fd = %d.\n",
04232             FSAL_FILENO(&(context->current_fd)));
04233 
04234   return 0;
04235 
04236 }
04237 
04241 int fn_fsal_read(int argc,      /* IN : number of args in argv */
04242                  char **argv,   /* IN : arg list               */
04243                  FILE * output  /* IN : output stream          */
04244     )
04245 {
04246 
04247   char format[] = "hvAXB:s:";
04248 
04249   const char help_read[] =
04250       "Usage:\n"
04251       "  read [-h][-v][-A][-X] [-B <block_size> ] [ -s <seek_type>,<offset> ]  { <total_bytes> | all }\n"
04252       "Options:\n"
04253       "  -h: print this help\n"
04254       "  -v: verbose mode\n"
04255       "  -A: display read data in ascii\n"
04256       "  -X: display read data in hexa\n"
04257       "  -B <blocksize>: block size used for reading, in bytes (default 1k).\n"
04258       "  -s <seek_type>,<offset>: specify the position of the first byte to be read.\n"
04259       "        <seek_type> can take the values SET, CUR or END.\n"
04260       "        <offset> is a signed integer.\n"
04261       "  <total_bytes>: indicates the total number of bytes to be read\n"
04262       "      ('all' indicates that data are read until the end of the file).\n"
04263       "Example:\n"
04264       "  For reading the last 2kB of the opened file, using 1k block size:\n"
04265       "        read -B 1024 -s END,-2048 all   \n";
04266 
04267   fsal_status_t st;
04268 
04269   int rc, option;
04270 
04271   int flag_v = 0;
04272   int flag_h = 0;
04273   int flag_A = 0;
04274   int flag_X = 0;
04275   int flag_B = 0;
04276   int flag_s = 0;
04277 
04278   int err_flag = 0;
04279 
04280   char *str_block_size = NULL;
04281 
04282   char str_seek_buff[256];
04283 
04284   char *str_seek_type = NULL;
04285   char *str_seek_offset = NULL;
04286   char *str_total_bytes = NULL;
04287 
04288   fsal_size_t block_size = 1024;        /* default: 1ko */
04289   fsal_size_t total_bytes = 0;  /* 0 == read all */
04290   fsal_seek_t seek_desc = { FSAL_SEEK_CUR, 0 }; /* default: read current position */
04291 
04292   fsal_seek_t *p_seek_desc = NULL;
04293 
04294   /* fsal arguments */
04295 
04296   fsal_boolean_t is_eof = 0;
04297   fsal_size_t total_nb_read = 0;
04298   fsal_size_t once_nb_read = 0;
04299   fsal_size_t nb_block_read = 0;
04300 
04301   char *p_read_buff;
04302 
04303   struct timeval timer_start;
04304   struct timeval timer_stop;
04305   struct timeval timer_diff;
04306 
04307   cmdfsal_thr_info_t *context;
04308 
04309   /* is the fs initialized ? */
04310   if(!is_loaded)
04311     {
04312       fprintf(output, "Error: filesystem not initialized\n");
04313       return -1;
04314     }
04315 
04316   /* initialize current thread */
04317 
04318   context = GetFSALCmdContext();
04319 
04320   if(context->is_thread_ok != TRUE)
04321     {
04322       int rc;
04323       rc = Init_Thread_Context(output, context, 0);
04324       if(rc != 0)
04325         return rc;
04326     }
04327 
04328   /* is a file opened ? */
04329   if(!context->opened)
04330     {
04331       fprintf(output, "Error: no opened file. Use 'open' command first.\n");
04332       return -1;
04333     }
04334 
04335   /* option analysis. */
04336 
04337   getopt_init();
04338   while((option = Getopt(argc, argv, format)) != -1)
04339     {
04340       switch (option)
04341         {
04342 
04343         case 'v':
04344           if(flag_v)
04345             fprintf(output,
04346                     "read: warning: option 'v' has been specified more than once.\n");
04347           else
04348             flag_v++;
04349           break;
04350 
04351         case 'h':
04352           if(flag_h)
04353             fprintf(output,
04354                     "read: warning: option 'h' has been specified more than once.\n");
04355           else
04356             flag_h++;
04357           break;
04358 
04359         case 'A':
04360           if(flag_A)
04361             fprintf(output,
04362                     "read: warning: option 'A' has been specified more than once.\n");
04363           else if(flag_X)
04364             {
04365               fprintf(output, "read: option 'A' conflicts with option 'X'.\n");
04366               err_flag++;
04367             }
04368           else
04369             flag_A++;
04370           break;
04371 
04372         case 'X':
04373           if(flag_X)
04374             fprintf(output,
04375                     "read: warning: option 'X' has been specified more than once.\n");
04376           else if(flag_A)
04377             {
04378               fprintf(output, "read: option 'X' conflicts with option 'A'.\n");
04379               err_flag++;
04380             }
04381           else
04382             flag_X++;
04383           break;
04384 
04385         case 'B':
04386           if(flag_B)
04387             fprintf(output,
04388                     "read: warning: option 'B' has been specified more than once.\n");
04389           else
04390             {
04391               flag_B++;
04392               str_block_size = Optarg;
04393             }
04394           break;
04395 
04396         case 's':
04397           if(flag_s)
04398             fprintf(output,
04399                     "read: warning: option 's' has been specified more than once.\n");
04400           else
04401             {
04402               flag_s++;
04403               strncpy(str_seek_buff, Optarg, 256);
04404               str_seek_type = str_seek_buff;
04405             }
04406           break;
04407 
04408         case '?':
04409           fprintf(output, "read: unknown option : %c\n", Optopt);
04410           err_flag++;
04411           break;
04412         }
04413     }
04414 
04415   if(flag_h)
04416     {
04417       fprintf(output, help_read);
04418       return 0;
04419     }
04420 
04421   /* Exactly one arg expected */
04422 
04423   if(Optind != (argc - 1))
04424     err_flag++;
04425   else
04426     str_total_bytes = argv[Optind];
04427 
04428   if(err_flag)
04429     {
04430       fprintf(output, help_read);
04431       return -1;
04432     }
04433 
04434   /* check argument types */
04435 
04436   if(flag_B)
04437     {
04438       /* Try to convert the str_block_size to fsal_size_t */
04439 
04440       rc = ato64(str_block_size, &block_size);
04441 
04442       if(rc == -1)
04443         {
04444           fprintf(output, "read: error: invalid block size \"%s\"\n", str_block_size);
04445           err_flag++;
04446         }
04447 
04448     }
04449 
04450   if(flag_s)
04451     {
04452       /* Try to parse the argument */
04453 
04454       str_seek_offset = strchr(str_seek_type, ',');
04455 
04456       if(str_seek_offset == NULL)
04457         {
04458           fprintf(output,
04459                   "read: error: invalid seek specifier \"%s\". <seek_type>,<offset> expected.\n",
04460                   str_seek_type);
04461           err_flag++;
04462         }
04463 
04464       if(!err_flag)
04465         {
04466           int sign = 1;
04467 
04468           *str_seek_offset = '\0';
04469           str_seek_offset++;    /* the first char after the "," */
04470 
04471           /* Check seek type */
04472 
04473           if(!strncmp(str_seek_type, "CUR", 256))
04474             seek_desc.whence = FSAL_SEEK_CUR;
04475           else if(!strncmp(str_seek_type, "SET", 256))
04476             seek_desc.whence = FSAL_SEEK_SET;
04477           else if(!strncmp(str_seek_type, "END", 256))
04478             seek_desc.whence = FSAL_SEEK_END;
04479           else
04480             {
04481               fprintf(output,
04482                       "read: error: invalid seek type \"%s\". CUR, SET or END expected.\n",
04483                       str_seek_type);
04484               err_flag++;
04485             }
04486 
04487           /* Try to convert str_seek_offset to fsal_off_t */
04488 
04489           switch (str_seek_offset[0])
04490             {
04491             case '+':
04492               sign = 1;
04493               str_seek_offset++;
04494               break;
04495 
04496             case '-':
04497               sign = -1;
04498               str_seek_offset++;
04499               break;
04500             }
04501 
04502           rc = ato64(str_seek_offset, (unsigned long long *)&seek_desc.offset);
04503 
04504           if(rc == -1)
04505             {
04506               fprintf(output, "read: error: invalid offset \"%s\".\n", str_seek_offset);
04507               err_flag++;
04508             }
04509           else if(sign < 0)
04510             seek_desc.offset = -seek_desc.offset;
04511 
04512         }
04513 
04514       p_seek_desc = &seek_desc;
04515 
04516     }
04517   else
04518     {
04519       p_seek_desc = NULL;       /* default seeking */
04520     }
04521 
04522   if(!strcasecmp(str_total_bytes, "all"))
04523     {
04524       total_bytes = 0;
04525     }
04526   else
04527     {
04528       rc = ato64(str_total_bytes, &total_bytes);
04529 
04530       if(rc == -1)
04531         {
04532           fprintf(output,
04533                   "read: error: invalid read size \"%s\". \"all\" or <nb_bytes> expected.\n",
04534                   str_total_bytes);
04535           err_flag++;
04536         }
04537     }
04538 
04539   if(err_flag)
04540     {
04541       fprintf(output, help_read);
04542       return -1;
04543     }
04544 
04545   if(flag_v)
04546     {
04547 
04548       /* print a sum-up of read parameters */
04549       fprintf(output,
04550               "Read options: Block size: %llu Bytes, Seek: %s%+lld, Read limit: %llu Bytes\n",
04551               block_size,
04552               (p_seek_desc
04553                ? (seek_desc.whence == FSAL_SEEK_SET ? "SET" : seek_desc.whence ==
04554                   FSAL_SEEK_CUR ? "CUR" : "END") : "DEFAULT"),
04555               (long long)(p_seek_desc ? seek_desc.offset : 0LL), total_bytes);
04556     }
04557 
04558   /* Now all arguments have been parsed, let's act ! */
04559 
04560   /* alloc a buffer */
04561   p_read_buff = gsh_malloc(block_size);
04562 
04563   if(p_read_buff == NULL)
04564     {
04565       fprintf(output,
04566               "read: error: Not enough memory to allocate read buffer (%llu Bytes).\n",
04567               block_size);
04568       return ENOMEM;
04569     }
04570 
04571   gettimeofday(&timer_start, NULL);
04572 
04573   /* while EOF is not reached, and read<asked (when total_bytes!=0) */
04574   while(!is_eof && !((total_bytes != 0) && (total_nb_read >= total_bytes)))
04575     {
04576 
04577       st = FSAL_read(&context->current_fd, p_seek_desc,
04578                      block_size, (caddr_t) p_read_buff, &once_nb_read, &is_eof);
04579 
04580       if(FSAL_IS_ERROR(st))
04581         {
04582           fprintf(output, "Error executing FSAL_read:");
04583           print_fsal_status(output, st);
04584           fprintf(output, "\n");
04585 
04586           /* exit only if it is not retryable */
04587           if(fsal_is_retryable(st))
04588             {
04589               sleep(1);
04590               continue;
04591             }
04592           else
04593             {
04594               gsh_free(p_read_buff);
04595               return st.major;
04596             }
04597         }
04598 
04599       /* print what was read. */
04600       if(flag_A)
04601         {
04602           fsal_size_t index;
04603           for(index = 0; index < once_nb_read; index++)
04604             fprintf(output, "%c.", p_read_buff[index]);
04605         }
04606       else if(flag_X)
04607         {
04608           fsal_size_t index;
04609           for(index = 0; index < once_nb_read; index++)
04610             fprintf(output, "%.2X ", p_read_buff[index]);
04611         }
04612       else
04613         fprintf(output, ".");
04614 
04615       /* update stats */
04616 
04617       if(once_nb_read > 0)
04618         nb_block_read++;
04619 
04620       total_nb_read += once_nb_read;
04621 
04622       /* flush */
04623       if(nb_block_read % 10)
04624         fflush(output);
04625 
04626       /* what ever seek type was, we continue reading from current position */
04627       p_seek_desc = NULL;
04628 
04629     }
04630 
04631   gettimeofday(&timer_stop, NULL);
04632 
04633   /* newline after read blocks */
04634   fprintf(output, "\n");
04635 
04636   if(flag_v)
04637     {
04638       double bandwidth;
04639 
04640       /* print stats */
04641       fprintf(output, "Nb blocks read: %llu\n", nb_block_read);
04642       fprintf(output, "Total: %llu Bytes\n", total_nb_read);
04643 
04644       fprintf(output, "Time enlapsed: ");
04645       timer_diff = time_diff(timer_start, timer_stop);
04646       print_timeval(output, timer_diff);
04647 
04648       bandwidth =
04649           total_nb_read / (1024 * 1024 *
04650                            (timer_diff.tv_sec + 0.000001 * timer_diff.tv_usec));
04651 
04652       fprintf(output, "Bandwidth: %f MB/s\n", bandwidth);
04653 
04654     }
04655   gsh_free(p_read_buff);
04656 
04657   return 0;
04658 }
04659 
04689 int fn_fsal_write(int argc,     /* IN : number of args in argv */
04690                   char **argv,  /* IN : arg list               */
04691                   FILE * output /* IN : output stream          */
04692     )
04693 {
04694 
04695   char format[] = "hvs:N:A:X:";
04696 
04697   const char help_write[] =
04698       "Usage:\n"
04699       "  write [-h][-v] [ -s <seek_type>,<offset> ]  [-N <nb_times>] -A <ascii_string>\n"
04700       "  write [-h][-v] [ -s <seek_type>,<offset> ]  [-N <nb_times>] -X <hexa_data>\n"
04701       "Where:\n"
04702       "  <seek_type> can be: SET, CUR, END\n"
04703       "  <offset> is a signed number of bytes.\n"
04704       "  <nb_times> is the number of times we write the expression into the file.\n"
04705       "\n"
04706       "  <ascii_string> is a string to be written to file.\n"
04707       "      Note that the null terminating character of is also written\n"
04708       "      to file.\n"
04709       "or\n"
04710       "  <hexa_data> is a data represented in hexadecimal format,\n"
04711       "      that is to be written to file.\n"
04712       "\n"
04713       "Examples:\n"
04714       "\n"
04715       "  For writting 10 times the null terminated string \"hello world\"\n"
04716       "  at the end of the file:\n"
04717       "        write -s END,0 -N 10 -A \"hello world\"\n"
04718       "\n"
04719       "  For overwritting the beginning of the file with\n"
04720       "  the pattern 0xA1267AEF31254ADE repeated twice:\n"
04721       "        write -s SET,0 -N 2 -X \"A1267AEF31254ADE\"\n";
04722 
04723   fsal_status_t st;
04724 
04725   int rc, option;
04726 
04727   int flag_v = 0;
04728   int flag_h = 0;
04729   int flag_N = 0;
04730   int flag_s = 0;
04731   int flag_A = 0;
04732   int flag_X = 0;
04733 
04734   int err_flag = 0;
04735 
04736   char *str_times = NULL;
04737   char str_seek_buff[256];
04738   char *str_seek_type = NULL;
04739   char *str_seek_offset = NULL;
04740 
04741   char *str_hexa = NULL;
04742   char *str_ascii = NULL;
04743 
04744   size_t datasize = 0;
04745   char *databuff = NULL;
04746 
04747   unsigned long long nb_times = 1;      /* default = 1 */
04748 
04749   fsal_size_t block_size;       /* the length of the data block to be written */
04750 
04751   fsal_u64_t nb_block_written = 0;
04752   fsal_size_t size_written = 0;
04753   fsal_size_t size_written_once = 0;
04754 
04755   fsal_seek_t seek_desc = { FSAL_SEEK_CUR, 0 }; /* default: write to current position */
04756 
04757   fsal_seek_t *p_seek_desc = NULL;
04758 
04759   struct timeval timer_start;
04760   struct timeval timer_stop;
04761   struct timeval timer_diff;
04762 
04763   cmdfsal_thr_info_t *context;
04764 
04765   /* is the fs initialized ? */
04766   if(!is_loaded)
04767     {
04768       fprintf(output, "Error: filesystem not initialized\n");
04769       return -1;
04770     }
04771 
04772   /* initialize current thread */
04773 
04774   context = GetFSALCmdContext();
04775 
04776   if(context->is_thread_ok != TRUE)
04777     {
04778       int rc;
04779       rc = Init_Thread_Context(output, context, 0);
04780       if(rc != 0)
04781         return rc;
04782     }
04783 
04784   /* is a file opened ? */
04785   if(!context->opened)
04786     {
04787       fprintf(output, "Error: no opened file. Use 'open' command first.\n");
04788       return -1;
04789     }
04790 
04791   /* option analysis. */
04792 
04793   getopt_init();
04794   while((option = Getopt(argc, argv, format)) != -1)
04795     {
04796       switch (option)
04797         {
04798 
04799         case 'v':
04800           if(flag_v)
04801             fprintf(output,
04802                     "write: warning: option 'v' has been specified more than once.\n");
04803           else
04804             flag_v++;
04805           break;
04806 
04807         case 'h':
04808           if(flag_h)
04809             fprintf(output,
04810                     "write: warning: option 'h' has been specified more than once.\n");
04811           else
04812             flag_h++;
04813           break;
04814 
04815         case 'N':
04816           if(flag_N)
04817             fprintf(output,
04818                     "write: warning: option 'N' has been specified more than once.\n");
04819           else
04820             {
04821               flag_N++;
04822               str_times = Optarg;
04823             }
04824           break;
04825 
04826         case 's':
04827           if(flag_s)
04828             fprintf(output,
04829                     "write: warning: option 's' has been specified more than once.\n");
04830           else
04831             {
04832               flag_s++;
04833               strncpy(str_seek_buff, Optarg, 256);
04834               str_seek_type = str_seek_buff;
04835             }
04836           break;
04837 
04838         case 'A':
04839           if(flag_A)
04840             fprintf(output,
04841                     "write: warning: option 'A' has been specified more than once.\n");
04842           else if(flag_X)
04843             {
04844               fprintf(output, "write: option 'A' conflicts with option 'X'.\n");
04845               err_flag++;
04846             }
04847           else
04848             {
04849               flag_A++;
04850               str_ascii = Optarg;
04851             }
04852           break;
04853 
04854         case 'X':
04855           if(flag_X)
04856             fprintf(output,
04857                     "write: warning: option 'X' has been specified more than once.\n");
04858           else if(flag_A)
04859             {
04860               fprintf(output, "write: option 'X' conflicts with option 'A'.\n");
04861               err_flag++;
04862             }
04863           else
04864             {
04865               flag_X++;
04866               str_hexa = Optarg;
04867             }
04868           break;
04869 
04870         case '?':
04871           fprintf(output, "write: unknown option : %c\n", Optopt);
04872           err_flag++;
04873           break;
04874         }
04875     }
04876 
04877   if(flag_h)
04878     {
04879       fprintf(output, help_write);
04880       return 0;
04881     }
04882 
04883   /* No extra arg expected */
04884 
04885   if(Optind != argc)
04886     err_flag++;
04887 
04888   if(!flag_A && !flag_X)
04889     {
04890       fprintf(output, "write: error: -A or -X option is mandatory.\n");
04891       err_flag++;
04892     }
04893 
04894   if(err_flag)
04895     {
04896       fprintf(output, help_write);
04897       return -1;
04898     }
04899 
04900   /* check argument types */
04901 
04902   if(flag_N)
04903     {
04904       /* Try to convert the str_times to nb_times */
04905 
04906       rc = ato64(str_times, &nb_times);
04907 
04908       if(rc == -1)
04909         {
04910           fprintf(output, "write: error: invalid number \"%s\"\n", str_times);
04911           return EINVAL;
04912         }
04913 
04914     }
04915 
04916   if(flag_s)
04917     {
04918       int sign = 1;
04919 
04920       /* Try to parse the argument */
04921 
04922       str_seek_offset = strchr(str_seek_type, ',');
04923 
04924       if(str_seek_offset == NULL)
04925         {
04926           fprintf(output,
04927                   "write: error: invalid seek specifier \"%s\". <seek_type>,<offset> expected.\n",
04928                   str_seek_type);
04929           return EINVAL;
04930         }
04931 
04932       *str_seek_offset = '\0';
04933       str_seek_offset++;        /* the first char after the "," */
04934 
04935       /* Check seek type */
04936 
04937       if(!strncmp(str_seek_type, "CUR", 256))
04938         seek_desc.whence = FSAL_SEEK_CUR;
04939       else if(!strncmp(str_seek_type, "SET", 256))
04940         seek_desc.whence = FSAL_SEEK_SET;
04941       else if(!strncmp(str_seek_type, "END", 256))
04942         seek_desc.whence = FSAL_SEEK_END;
04943       else
04944         {
04945           fprintf(output,
04946                   "write: error: invalid seek type \"%s\". CUR, SET or END expected.\n",
04947                   str_seek_type);
04948           return EINVAL;
04949         }
04950 
04951       /* Try to convert str_seek_offset to fsal_off_t */
04952 
04953       switch (str_seek_offset[0])
04954         {
04955         case '+':
04956           sign = 1;
04957           str_seek_offset++;
04958           break;
04959 
04960         case '-':
04961           sign = -1;
04962           str_seek_offset++;
04963           break;
04964         }
04965 
04966       rc = ato64(str_seek_offset, (unsigned long long *)&seek_desc.offset);
04967 
04968       if(rc == -1)
04969         {
04970           fprintf(output, "write: error: invalid offset \"%s\".\n", str_seek_offset);
04971           return EINVAL;
04972         }
04973       else if(sign < 0)
04974         seek_desc.offset = -seek_desc.offset;
04975 
04976       p_seek_desc = &seek_desc;
04977 
04978     }
04979   else
04980     {
04981       p_seek_desc = NULL;       /* default seeking */
04982     }
04983 
04984   if(flag_A)
04985     {
04986       datasize = strlen(str_ascii) + 1; /* Include null termination char. */
04987       databuff = str_ascii;
04988     }
04989 
04990   if(flag_X)
04991     {
04992       size_t length = strlen(str_hexa);
04993 
04994       datasize = (length >> 1);
04995 
04996       if(length % 2)
04997         {
04998 
04999           /* if it is not odd: error */
05000           fprintf(output,
05001                   "write: error: in \"%s\", data length is not a multiple of 8 bits.\n",
05002                   str_hexa);
05003 
05004           return EINVAL;
05005         }
05006 
05007       databuff = gsh_calloc(1, datasize + 1);
05008 
05009       if(databuff == NULL)
05010         {
05011           fprintf(output, "write: error: Not enough memory to allocate %zu Bytes.\n",
05012                   datasize);
05013           return ENOMEM;
05014         }
05015 
05016       /* try to convert the string to hexa */
05017       rc = sscanmem(databuff, datasize, str_hexa);
05018 
05019       if(rc != (int)(2 * datasize))
05020         {
05021           /* if it is not odd: error */
05022           fprintf(output, "write: error: \"%s\" in not a valid hexa format.\n", str_hexa);
05023 
05024           gsh_free(str_hexa);
05025 
05026           return EINVAL;
05027         }
05028 
05029     }
05030 
05031   if(flag_v)
05032     {
05033       /* print a sum-up of write parameters */
05034       fprintf(output, "Write options: Data length: %llu x %llu Bytes, Seek: %s%+lld\n",
05035               (unsigned long long)nb_times,
05036               (unsigned long long)datasize,
05037               (p_seek_desc ? (seek_desc.whence == FSAL_SEEK_SET ? "SET" :
05038                               seek_desc.whence == FSAL_SEEK_CUR ? "CUR" :
05039                               "END") : "DEFAULT"),
05040               (p_seek_desc ? seek_desc.offset : 0LL));
05041     }
05042 
05043   /* variables initialisation */
05044 
05045   block_size = (fsal_size_t) datasize;
05046   nb_block_written = 0;
05047   size_written = 0;
05048   size_written_once = 0;
05049 
05050   gettimeofday(&timer_start, NULL);
05051 
05052   /* write loop */
05053 
05054   while(nb_block_written < nb_times)
05055     {
05056 
05057       st = FSAL_write(&context->current_fd, &context->context,  p_seek_desc,
05058                       block_size, (caddr_t) databuff, &size_written_once);
05059 
05060       if(FSAL_IS_ERROR(st))
05061         {
05062           fprintf(output, "Error executing FSAL_write:");
05063           print_fsal_status(output, st);
05064           fprintf(output, "\n");
05065 
05066           /* exit only if it is not retryable */
05067           if(fsal_is_retryable(st))
05068             {
05069               sleep(1);
05070               continue;
05071             }
05072           else
05073             {
05074               if(flag_X)
05075                 gsh_free(databuff);
05076               return st.major;
05077             }
05078         }
05079 
05080       fprintf(output, ".");
05081 
05082       /* update stats */
05083 
05084       if(size_written_once > 0)
05085         nb_block_written++;
05086 
05087       size_written += size_written_once;
05088 
05089       /* flush */
05090       if(nb_block_written % 10)
05091         fflush(output);
05092 
05093       /* what ever seek type was, we continue writting to the current position */
05094       p_seek_desc = NULL;
05095 
05096     }
05097 
05098   gettimeofday(&timer_stop, NULL);
05099 
05100   /* newline after written blocks */
05101   fprintf(output, "\n");
05102 
05103   if(flag_v)
05104     {
05105       double bandwidth;
05106 
05107       /* print stats */
05108       fprintf(output, "Nb blocks written: %llu\n", nb_block_written);
05109       fprintf(output, "Total volume: %llu Bytes\n", size_written);
05110 
05111       fprintf(output, "Time enlapsed: ");
05112       timer_diff = time_diff(timer_start, timer_stop);
05113       print_timeval(output, timer_diff);
05114 
05115       bandwidth =
05116           size_written / (1024 * 1024 *
05117                           (timer_diff.tv_sec + 0.000001 * timer_diff.tv_usec));
05118 
05119       fprintf(output, "Bandwidth: %f MB/s\n", bandwidth);
05120 
05121     }
05122 
05123   if(flag_X)
05124     gsh_free(databuff);
05125 
05126   return 0;
05127 
05128 }
05129 
05134 int fn_fsal_close(int argc,     /* IN : number of args in argv */
05135                   char **argv,  /* IN : arg list               */
05136                   FILE * output /* IN : output stream          */
05137     )
05138 {
05139 
05140   const char help_close[] = "usage: close\n";
05141 
05142   fsal_status_t st;
05143 
05144   cmdfsal_thr_info_t *context;
05145 
05146   /* is the fs initialized ? */
05147   if(!is_loaded)
05148     {
05149       fprintf(output, "Error: filesystem not initialized\n");
05150       return -1;
05151     }
05152 
05153   /* initialize current thread */
05154 
05155   context = GetFSALCmdContext();
05156 
05157   if(context->is_thread_ok != TRUE)
05158     {
05159       int rc;
05160       rc = Init_Thread_Context(output, context, 0);
05161       if(rc != 0)
05162         return rc;
05163     }
05164 
05165   /* is a file already opened ? */
05166   if(!context->opened)
05167     {
05168       fprintf(output, "Error: this is no file currently opened.\n");
05169       return -1;
05170     }
05171 
05172   if(argc != 1)
05173     {
05174       fprintf(output, help_close);
05175       return -1;
05176     }
05177 
05178   st = FSAL_close(&context->current_fd);
05179 
05180   if(FSAL_IS_ERROR(st))
05181     {
05182       fprintf(output, "Error executing FSAL_close:");
05183       print_fsal_status(output, st);
05184       fprintf(output, "\n");
05185       return st.major;
05186     }
05187 
05188   /* note that a file is closed. */
05189   context->opened = FALSE;
05190 
05191   return 0;
05192 
05193 }
05194 
05199 int fn_fsal_close_byfileid(int argc,    /* IN : number of args in argv */
05200                            char **argv, /* IN : arg list               */
05201                            FILE * output        /* IN : output stream          */
05202     )
05203 {
05204 
05205   const char help_close[] = "usage: close_byfileid <fileid>\n";
05206 
05207   fsal_status_t st;
05208 
05209   cmdfsal_thr_info_t *context;
05210 
05211   /* is the fs initialized ? */
05212   if(!is_loaded)
05213     {
05214       fprintf(output, "Error: filesystem not initialized\n");
05215       return -1;
05216     }
05217 
05218   /* initialize current thread */
05219 
05220   context = GetFSALCmdContext();
05221 
05222   if(context->is_thread_ok != TRUE)
05223     {
05224       int rc;
05225       rc = Init_Thread_Context(output, context, 0);
05226       if(rc != 0)
05227         return rc;
05228     }
05229 
05230   /* is a file already opened ? */
05231   if(!context->opened)
05232     {
05233       fprintf(output, "Error: this is no file currently opened.\n");
05234       return -1;
05235     }
05236 
05237   if(argc != 1)
05238     {
05239       fprintf(output, help_close);
05240       return -1;
05241     }
05242 
05243   st = FSAL_close(&context->current_fd);
05244 
05245   if(FSAL_IS_ERROR(st))
05246     {
05247       fprintf(output, "Error executing FSAL_close:");
05248       print_fsal_status(output, st);
05249       fprintf(output, "\n");
05250       return st.major;
05251     }
05252 
05253   /* note that a file is closed. */
05254   context->opened = FALSE;
05255 
05256   return 0;
05257 
05258 }
05259 
05264 int fn_fsal_cat(int argc,       /* IN : number of args in argv */
05265                 char **argv,    /* IN : arg list               */
05266                 FILE * output   /* IN : output stream          */
05267     )
05268 {
05269 
05270   char format[] = "hf";
05271 
05272   const char help_cat[] =
05273       "usage: cat [-h][-f] <path>\n"
05274       "   -h: print this help\n"
05275       "   -f: by default, cat doesn't print more that 1MB.\n"
05276       "       this option force it to print the whole file.\n";
05277 
05278   char glob_path[FSAL_MAX_PATH_LEN];
05279   fsal_handle_t filehdl;
05280 
05281   fsal_status_t st;
05282 
05283   int rc, option;
05284   int flag_h = 0;
05285   int flag_f = 0;
05286   int err_flag = 0;
05287 
05288   fsal_openflags_t o_flags;
05289   fsal_file_t cat_fd;
05290 
05291 #define MAX_CAT_SIZE  (1024*1024)
05292   fsal_size_t nb_read = 0;
05293   fsal_size_t buffsize = 1024;
05294   char readbuff[1024];
05295   int is_eof = 0;
05296 
05297   char *file = NULL;
05298 
05299   cmdfsal_thr_info_t *context;
05300 
05301   /* is the fs initialized ? */
05302   if(!is_loaded)
05303     {
05304       fprintf(output, "Error: filesystem not initialized\n");
05305       return -1;
05306     }
05307 
05308   /* initialize current thread */
05309 
05310   context = GetFSALCmdContext();
05311 
05312   if(context->is_thread_ok != TRUE)
05313     {
05314       int rc;
05315       rc = Init_Thread_Context(output, context, 0);
05316       if(rc != 0)
05317         return rc;
05318     }
05319 
05320   /* analysing options */
05321 
05322   getopt_init();
05323   while((option = Getopt(argc, argv, format)) != -1)
05324     {
05325       switch (option)
05326         {
05327         case 'f':
05328           if(flag_f)
05329             fprintf(output,
05330                     "cat: warning: option 'f' has been specified more than once.\n");
05331           else
05332             flag_f++;
05333           break;
05334         case 'h':
05335           if(flag_h)
05336             fprintf(output,
05337                     "cat: warning: option 'h' has been specified more than once.\n");
05338           else
05339             flag_h++;
05340           break;
05341         case '?':
05342           fprintf(output, "cat: unknown option : %c\n", Optopt);
05343           err_flag++;
05344           break;
05345         }
05346     }
05347 
05348   if(flag_h)
05349     {
05350       fprintf(output, help_cat);
05351       return 0;
05352     }
05353 
05354   /* one arg expected */
05355   if(Optind != (argc - 1))
05356     err_flag++;
05357   else
05358     file = argv[Optind];
05359 
05360   if(err_flag)
05361     {
05362       fprintf(output, help_cat);
05363       return -1;
05364     }
05365 
05366   /* copy current path. */
05367   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
05368 
05369   /* retrieves object handle */
05370   if((rc =
05371      solvepath(glob_path, FSAL_MAX_PATH_LEN,
05372                file, context->current_dir, &filehdl, output)))
05373     return rc;
05374 
05375   /* make open flags */
05376 
05377   o_flags = FSAL_O_RDONLY;
05378 
05379   st = FSAL_open(&filehdl, &context->context, o_flags, &cat_fd, NULL);
05380 
05381   if(FSAL_IS_ERROR(st))
05382     {
05383       fprintf(output, "Error executing FSAL_open:");
05384       print_fsal_status(output, st);
05385       fprintf(output, "\n");
05386       return st.major;
05387     }
05388 
05389   /* read operations */
05390 
05391   while(!is_eof && (flag_f || (nb_read < MAX_CAT_SIZE)))
05392     {
05393       fsal_size_t nb_read_once;
05394 
05395       st = FSAL_read(&cat_fd, NULL, buffsize, (caddr_t) readbuff, &nb_read_once, &is_eof);
05396 
05397       if(FSAL_IS_ERROR(st))
05398         {
05399           fprintf(output, "Error executing FSAL_read:");
05400           print_fsal_status(output, st);
05401           fprintf(output, "\n");
05402 
05403           /* exit only if it is not retryable */
05404           if(fsal_is_retryable(st))
05405             {
05406               sleep(1);
05407               continue;
05408             }
05409           else
05410             return st.major;
05411         }
05412 
05413       if (fwrite((caddr_t) readbuff, (size_t) nb_read_once, 1, output));
05414 
05415       /* update stats */
05416       nb_read += nb_read_once;
05417 
05418     }
05419 
05420   FSAL_close(&cat_fd);
05421 
05422   if(!is_eof)
05423     {
05424       fprintf(output,
05425               "\n----------------- File is larger than 1MB (use -f option to display all) -----------------\n");
05426       return EPERM;
05427     }
05428 
05429   return 0;
05430 
05431 }
05432 
05437 int fn_fsal_rcp(int argc,       /* IN : number of args in argv */
05438                 char **argv,    /* IN : arg list               */
05439                 FILE * output   /* IN : output stream          */
05440     )
05441 {
05442 
05443   char format[] = "hvrw";
05444 
05445   const char help_rcp[] =
05446       "usage: rcp [-h][-v] -r|-w <fsal_path> <local_path>\n"
05447       "  -h : print this help\n"
05448       "  -v : verbose mode\n"
05449       "copy direction:\n"
05450       "  -r : FSAL -> local filesystem\n" "  -w : local filesystem -> FSAL\n";
05451 
05452   char glob_path[FSAL_MAX_PATH_LEN];
05453   fsal_handle_t filehdl;
05454 
05455   fsal_status_t st;
05456 
05457   int rc, option;
05458   int flag_h = 0;
05459   int flag_v = 0;
05460   int flag_r = 0;
05461   int flag_w = 0;
05462 
05463   int err_flag = 0;
05464 
05465   char *local_file = NULL;
05466   char *fsal_file = NULL;
05467 
05468   fsal_path_t local_path_fsal;
05469   fsal_rcpflag_t rcp_opt;
05470 
05471   cmdfsal_thr_info_t *context;
05472 
05473   /* is the fs initialized ? */
05474   if(!is_loaded)
05475     {
05476       fprintf(output, "Error: filesystem not initialized\n");
05477       return -1;
05478     }
05479 
05480   /* initialize current thread */
05481 
05482   context = GetFSALCmdContext();
05483 
05484   if(context->is_thread_ok != TRUE)
05485     {
05486       int rc;
05487       rc = Init_Thread_Context(output, context, 0);
05488       if(rc != 0)
05489         return rc;
05490     }
05491 
05492   /* analysing options */
05493 
05494   getopt_init();
05495   while((option = Getopt(argc, argv, format)) != -1)
05496     {
05497       switch (option)
05498         {
05499         case 'r':
05500           if(flag_w)
05501             {
05502               fprintf(output, "rcp: error: option 'r' conflicts with option 'w'.\n");
05503               err_flag++;
05504             }
05505           else if(flag_r)
05506             fprintf(output,
05507                     "rcp: warning: option 'r' has been specified more than once.\n");
05508           else
05509             flag_r++;
05510           break;
05511         case 'w':
05512           if(flag_r)
05513             {
05514               fprintf(output, "rcp: error: option 'w' conflicts with option 'r'.\n");
05515               err_flag++;
05516             }
05517           else if(flag_w)
05518             fprintf(output,
05519                     "rcp: warning: option 'w' has been specified more than once.\n");
05520           else
05521             flag_w++;
05522           break;
05523         case 'h':
05524           if(flag_h)
05525             fprintf(output,
05526                     "rcp: warning: option 'h' has been specified more than once.\n");
05527           else
05528             flag_h++;
05529           break;
05530         case 'v':
05531           if(flag_v)
05532             fprintf(output,
05533                     "rcp: warning: option 'v' has been specified more than once.\n");
05534           else
05535             flag_v++;
05536           break;
05537         case '?':
05538           fprintf(output, "rcp: unknown option : %c\n", Optopt);
05539           err_flag++;
05540           break;
05541         }
05542     }
05543 
05544   if(flag_h)
05545     {
05546       fprintf(output, help_rcp);
05547       return 0;
05548     }
05549 
05550   /* two args expected */
05551   if(Optind != (argc - 2))
05552     err_flag++;
05553   else
05554     {
05555       fsal_file = argv[Optind];
05556       local_file = argv[Optind + 1];
05557     }
05558 
05559   if(err_flag)
05560     {
05561       fprintf(output, help_rcp);
05562       return -1;
05563     }
05564 
05565   /* copy current path. */
05566   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
05567 
05568   /* retrieves object handle */
05569 
05570   if((rc =
05571      solvepath(glob_path, FSAL_MAX_PATH_LEN,
05572                fsal_file, context->current_dir, &filehdl, output)))
05573     return rc;
05574 
05575   /* build fsal path strcuture for local file */
05576 
05577   st = FSAL_str2path(local_file, strlen(local_file) + 1, &local_path_fsal);
05578 
05579   if(FSAL_IS_ERROR(st))
05580     {
05581 
05582       fprintf(output, "Error executing FSAL_str2path:");
05583       print_fsal_status(output, st);
05584       fprintf(output, "\n");
05585       return st.major;
05586 
05587     }
05588 
05589   /* make rcp flags */
05590 
05591   if(flag_r)
05592     rcp_opt = FSAL_RCP_FS_TO_LOCAL | FSAL_RCP_LOCAL_CREAT;
05593   else
05594     rcp_opt = FSAL_RCP_LOCAL_TO_FS;
05595 
05596   if(flag_v)
05597     {
05598       fprintf(output, "rcp: calling FSAL_rcp with options: ");
05599 
05600       if(rcp_opt & FSAL_RCP_FS_TO_LOCAL)
05601         fprintf(output, "FSAL_RCP_FS_TO_LOCAL ");
05602 
05603       if(rcp_opt & FSAL_RCP_LOCAL_TO_FS)
05604         fprintf(output, "FSAL_RCP_LOCAL_TO_FS ");
05605 
05606       if(rcp_opt & FSAL_RCP_LOCAL_EXCL)
05607         fprintf(output, "FSAL_RCP_LOCAL_EXCL ");
05608 
05609       if(rcp_opt & FSAL_RCP_LOCAL_CREAT)
05610         fprintf(output, "FSAL_RCP_LOCAL_CREAT ");
05611 
05612       fprintf(output, "\n");
05613     }
05614 
05615   /* rcp operation */
05616 
05617   st = FSAL_rcp(&filehdl, &context->context, &local_path_fsal, rcp_opt);
05618 
05619   if(FSAL_IS_ERROR(st))
05620     {
05621       fprintf(output, "Error executing FSAL_rcp:");
05622       print_fsal_status(output, st);
05623       fprintf(output, "\n");
05624       return st.major;
05625     }
05626 
05627   if(flag_v)
05628     {
05629       if(flag_r)
05630         fprintf(output, "rcp operation successfully completed : %s -> %s\n", glob_path,
05631                 local_file);
05632       else
05633         fprintf(output, "rcp operation successfully completed : %s -> %s\n", local_file,
05634                 glob_path);
05635     }
05636 
05637   return 0;
05638 
05639 }
05640 
05642 int fn_fsal_cross(int argc,     /* IN : number of args in argv */
05643                   char **argv,  /* IN : arg list               */
05644                   FILE * output /* IN : output stream          */
05645     )
05646 {
05647 
05648   const char help_cross[] = "usage: cross <junction_path>\n";
05649 
05650   char glob_path[FSAL_MAX_PATH_LEN];
05651   fsal_handle_t junction_hdl, root_hdl;
05652   fsal_attrib_list_t attrs;
05653   fsal_status_t st;
05654   int rc;
05655 
05656   cmdfsal_thr_info_t *context;
05657 
05658   /* is the fs initialized ? */
05659   if(!is_loaded)
05660     {
05661       fprintf(output, "Error: filesystem not initialized\n");
05662       return -1;
05663     }
05664 
05665   /* initialize current thread */
05666 
05667   context = GetFSALCmdContext();
05668 
05669   if(context->is_thread_ok != TRUE)
05670     {
05671       int rc;
05672       rc = Init_Thread_Context(output, context, 0);
05673       if(rc != 0)
05674         return rc;
05675     }
05676 
05677   /* Exactly one arg expected */
05678   if(argc != 2)
05679     {
05680       fprintf(output, help_cross);
05681       return -1;
05682     }
05683 
05684   /* is it a relative or absolute path. */
05685   strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
05686 
05687   if((rc =
05688      solvepath(glob_path, FSAL_MAX_PATH_LEN,
05689                argv[1], context->current_dir, &junction_hdl, output)))
05690     return rc;
05691 
05692   /* solves the junction */
05693   FSAL_CLEAR_MASK(attrs.asked_attributes);
05694   FSAL_SET_MASK(attrs.asked_attributes,
05695                 FSAL_ATTR_TYPE | FSAL_ATTR_MODE | FSAL_ATTR_GROUP | FSAL_ATTR_OWNER);
05696 
05697   st = FSAL_lookupJunction(&junction_hdl, &context->context, &root_hdl, NULL);
05698 
05699   if(FSAL_IS_ERROR(st))
05700     {
05701       char buff[2 * sizeof(fsal_handle_t) + 1];
05702       snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &junction_hdl);
05703 
05704       fprintf(output, "Error executing FSAL_lookupJunction(@%s):", buff);
05705       print_fsal_status(output, st);
05706       fprintf(output, "\n");
05707       return st.major;
05708     }
05709 
05710   /* Apply changes */
05711   strncat(glob_path, ">", FSAL_MAX_PATH_LEN);
05712   strncpy(context->current_path, glob_path, FSAL_MAX_PATH_LEN);
05713   context->current_dir = root_hdl;
05714 
05715   {
05716     char buff[2 * sizeof(fsal_handle_t) + 1];
05717     snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &context->current_dir);
05718 
05719     fprintf(output, "Current directory is \"%s\" (@%s)\n", context->current_path, buff);
05720   }
05721 
05722   return 0;
05723 
05724 }
05725 
05727 int fn_fsal_handle(int argc,     /* IN : number of args in argv */
05728                    char **argv,  /* IN : arg list               */
05729                    FILE * output /* IN : output stream          */
05730     )
05731 {
05732 
05733   const char help_handle[] = "usage: handle digest {2|3|4} <handle|path>\n"
05734                               "       handle expand {2|3|4} <handle>\n";
05735   cmdfsal_thr_info_t *context;
05736   char glob_path[FSAL_MAX_PATH_LEN];
05737   char buff[1024];
05738   char buff2[1024];
05739   fsal_handle_t filehdl;
05740   struct fsal_handle_desc fh_desc;
05741   fsal_status_t st;
05742   int rc;
05743   fsal_digesttype_t dt ; /* digest type */
05744   size_t            ds ; /* digest size */
05745 
05746 
05747   /* is the fs initialized ? */
05748   if(!is_loaded)
05749     {
05750       fprintf(output, "Error: filesystem not initialized\n");
05751       return -1;
05752     }
05753 
05754   /* initialize current thread */
05755 
05756   context = GetFSALCmdContext();
05757 
05758   if(context->is_thread_ok != TRUE)
05759     {
05760       int rc;
05761       rc = Init_Thread_Context(output, context, 0);
05762       if(rc != 0)
05763         return rc;
05764     }
05765 
05766   /* Exactly 3 args expected */
05767   if(argc != 4)
05768     {
05769       fprintf(output, help_handle);
05770       return -1;
05771     }
05772 
05773   switch( atoi(argv[2]) )
05774   {
05775         case 2:
05776                 dt = FSAL_DIGEST_NFSV2;
05777                 ds = FSAL_DIGEST_SIZE_HDLV2;
05778                 break;
05779         case 3:
05780                 dt = FSAL_DIGEST_NFSV3;
05781                 ds = FSAL_DIGEST_SIZE_HDLV3;
05782                 break;
05783         case 4:
05784                 dt = FSAL_DIGEST_NFSV4;
05785                 ds = FSAL_DIGEST_SIZE_HDLV4;
05786                 break;
05787         default:
05788                 fprintf(output, "Unsupported NFS version: '%s' (2, 3 or 4 expected)\n", argv[2]);
05789                 fprintf(output, help_handle);
05790                 return EINVAL;
05791   }
05792 
05793   /* digest operation */
05794   if ( !strcmp(argv[1], "digest") )
05795   {
05796         /* retrieves object handle */
05797         strncpy(glob_path, context->current_path, FSAL_MAX_PATH_LEN);
05798         if((rc = solvepath(glob_path, FSAL_MAX_PATH_LEN,
05799                            argv[3], context->current_dir, &filehdl, output)))
05800                 return rc;
05801 
05802         fh_desc.start = buff;
05803         fh_desc.len = sizeof(buff);
05804         st = FSAL_DigestHandle(&context->exp_context, dt, &filehdl, &fh_desc);
05805         if(FSAL_IS_ERROR(st))
05806         {
05807               snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &filehdl);
05808               fprintf(output, "Error executing FSAL_DigestHandle(@%s):", buff);
05809               print_fsal_status(output, st);
05810               fprintf(output, "\n");
05811               return st.major;
05812         }
05813         /* display the result */
05814         snprintmem(buff2, 1024, buff, ds);
05815         fprintf(output, "%s\n", buff2);
05816   }
05817   /* expand operation */
05818   else if ( !strcmp(argv[1], "expand") )
05819   {
05820         memset(buff, 0, 1024);
05821         size_t length = strlen(argv[3]);
05822         size_t datasize = (length >> 1);
05823 
05824         if(length % 2)
05825         {
05826           /* if it is not odd: error */
05827           fprintf(output,
05828                   "handle expand: error: in \"%s\", data length is not a multiple of 8 bits.\n",
05829                   argv[3]);
05830           return EINVAL;
05831         }
05832 
05833         /* try to read hexa from the string */
05834         rc = sscanmem(buff, datasize, argv[3]);
05835 
05836         if (rc < 0)
05837         {
05838                 fprintf(output, "Error %d reading digest from command line (%s)",
05839                         -rc, argv[3]);
05840                 return rc;
05841         }
05842         else if (rc != 2*ds)
05843         {
05844                 fprintf(output, "Unexpected data size for digest type NFSv%s: 2x%zu expected, %u read\n",
05845                         argv[2], ds, rc);
05846                 return EINVAL;
05847         }
05848 
05849         fh_desc.start = buff;
05850         fh_desc.len = length;
05851         /* Expand the handle */
05852         st = FSAL_ExpandHandle(&context->exp_context, dt, &fh_desc);
05853         if(FSAL_IS_ERROR(st))
05854         {
05855               fprintf(output, "Error executing FSAL_ExpandHandle(%s):", argv[3]);
05856               print_fsal_status(output, st);
05857               fprintf(output, "\n");
05858               return st.major;
05859         }
05860 
05861         snprintHandle(buff2, 2 * fh_desc.len + 1, fh_desc.start);
05862         fprintf(output, "@%s\n", buff2);
05863   }
05864   else
05865   {
05866       fprintf(output, help_handle);
05867       return -1;
05868   }
05869   return 0;
05870 }
05871 
05872 
05873 
05875 int fn_fsal_handlecmp(int argc, /* IN : number of args in argv */
05876                       char **argv,      /* IN : arg list   */
05877                       FILE * output     /* IN : output stream */
05878     )
05879 {
05880   const char help_handlecmp[] = "usage: handlecmp <obj1> <obj2>\n";
05881 
05882   char glob_path1[FSAL_MAX_PATH_LEN];
05883   char glob_path2[FSAL_MAX_PATH_LEN];
05884   char buff[2 * sizeof(fsal_handle_t) + 1];
05885 
05886   fsal_handle_t hdl1, hdl2;
05887   fsal_status_t st;
05888   int rc;
05889 
05890   cmdfsal_thr_info_t *context;
05891 
05892   /* is the fs initialized ? */
05893   if(!is_loaded)
05894     {
05895       fprintf(output, "Error: filesystem not initialized\n");
05896       return -1;
05897     }
05898 
05899   /* initialize current thread */
05900 
05901   context = GetFSALCmdContext();
05902 
05903   if(context->is_thread_ok != TRUE)
05904     {
05905       int rc;
05906       rc = Init_Thread_Context(output, context, 0);
05907       if(rc != 0)
05908         return rc;
05909     }
05910 
05911   /* Exactly 2 args expected */
05912   if(argc != 3)
05913     {
05914       fprintf(output, help_handlecmp);
05915       return -1;
05916     }
05917 
05918   strncpy(glob_path1, context->current_path, FSAL_MAX_PATH_LEN);
05919   strncpy(glob_path2, context->current_path, FSAL_MAX_PATH_LEN);
05920 
05921   if((rc =
05922      solvepath(glob_path1, FSAL_MAX_PATH_LEN,
05923                argv[1], context->current_dir, &hdl1, output)))
05924     return rc;
05925 
05926   if((rc =
05927      solvepath(glob_path2, FSAL_MAX_PATH_LEN,
05928                argv[2], context->current_dir, &hdl2, output)))
05929     return rc;
05930 
05931   /* it should return :
05932    *  - 0 if handle are the same
05933    *    - A non null value else.
05934    */
05935   rc = FSAL_handlecmp(&hdl1, &hdl2, &st);
05936 
05937   if(FSAL_IS_ERROR(st))
05938     {
05939       fprintf(output, "Error executing FSAL_handlecmp:");
05940       print_fsal_status(output, st);
05941       fprintf(output, "\n");
05942       return st.major;
05943     }
05944 
05945   snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &hdl1);
05946   fprintf(output, "%s: handle = @%s\n", argv[1], buff);
05947 
05948   snprintHandle(buff, 2 * sizeof(fsal_handle_t) + 1, &hdl2);
05949   fprintf(output, "%s: handle = @%s\n", argv[2], buff);
05950 
05951   if(rc == 0)
05952     {
05953       fprintf(output, "Handles are identical.\n");
05954       return rc;
05955     }
05956   else
05957     {
05958       fprintf(output, "Handles are different.\n");
05959       return rc;
05960     }
05961 
05962   return 0;
05963 }