nfs-ganesha 1.4

cmd_tools.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 
00106 #ifdef HAVE_CONFIG_H
00107 #include "config.h"
00108 #endif
00109 
00110 #include <strings.h>
00111 #include <string.h>
00112 #include <errno.h>
00113 #include <err_ghost_fs.h>
00114 #include <sys/types.h>
00115 #include <unistd.h>
00116 #include <time.h>
00117 #include <pthread.h>
00118 #include "cmd_tools.h"
00119 #include <grp.h>
00120 
00121 /* mutex for calling localtime... */
00122 static pthread_mutex_t mutex_localtime = PTHREAD_MUTEX_INITIALIZER;
00123 
00124 /* thread-safe and PORTABLE version of localtime... */
00125 struct tm *Localtime_r(const time_t * p_time, struct tm *p_tm)
00126 {
00127   struct tm *p_tmp_tm;
00128 
00129   if(!p_tm)
00130     {
00131       errno = EFAULT;
00132       return NULL;
00133     }
00134 
00135   pthread_mutex_lock(&mutex_localtime);
00136 
00137   p_tmp_tm = localtime(p_time);
00138 
00139   /* copy the result */
00140   (*p_tm) = (*p_tmp_tm);
00141 
00142   pthread_mutex_unlock(&mutex_localtime);
00143 
00144   return p_tm;
00145 }
00146 
00156 int my_atoi(char *str)
00157 {
00158 
00159   int i;
00160   int out = 0;
00161 
00162   for(i = 0; str[i]; i++)
00163     {
00164 
00165       if((str[i] < '0') || (str[i] > '9'))
00166         return -1;              /* error */
00167       else
00168         {
00169           out *= 10;
00170           out += (int)(str[i] - '0');
00171         }
00172     }
00173 
00174   if(i == 0)
00175     return -1;
00176 
00177   return out;
00178 
00179 }
00180 
00190 int atomode(char *str)
00191 {
00192 
00193   int i;
00194   int out = 0;
00195 
00196   for(i = 0; str[i]; i++)
00197     {
00198 
00199       if((str[i] < '0') || (str[i] > '7'))
00200         return -1;              /* error */
00201       else
00202         {
00203           out *= 8;
00204           out += (int)(str[i] - '0');
00205         }
00206     }
00207 
00208   if(i < 3)
00209     return -1;
00210 
00211   return out;
00212 
00213 }
00214 
00215 int ato64(char *str, unsigned long long *out64)
00216 {
00217 
00218   int i;
00219   unsigned long long out = 0;
00220 
00221   if(!out64)
00222     return -1;
00223 
00224   for(i = 0; str[i]; i++)
00225     {
00226 
00227       if((str[i] < '0') || (str[i] > '9'))
00228         return -1;              /* error */
00229       else
00230         {
00231           out *= 10;
00232           out += (unsigned long long)(str[i] - '0');
00233         }
00234     }
00235 
00236   if(i == 0)
00237     return -1;
00238 
00239   *out64 = out;
00240 
00241   return 0;
00242 }
00243 
00247 time_t atotime(char *str)
00248 {
00249 
00250   struct tm time_struct;
00251 
00252   char tmp_str[16];
00253   int i, j, rc;
00254 
00255   /* init tm */
00256 
00257   memset(&time_struct, 0, sizeof(struct tm));
00258 
00259   /* parsing year */
00260 
00261   j = 0;
00262   for(i = 0; i < 4; i++)
00263     {
00264       if(!str[i])
00265         return (time_t) - 1;
00266       tmp_str[j] = str[i];
00267       j++;
00268     }
00269   tmp_str[j] = '\0';
00270   j++;
00271 
00272   rc = my_atoi(tmp_str);
00273   if(rc == -1)
00274     return (time_t) - 1;
00275 
00276   time_struct.tm_year = rc - 1900;
00277 
00278 /*  printf("Year: %d\n",rc);*/
00279 
00280   /* parsing month */
00281 
00282   j = 0;
00283   for(i = 4; i < 6; i++)
00284     {
00285       if(!str[i])
00286         return (time_t) - 1;
00287       tmp_str[j] = str[i];
00288       j++;
00289     }
00290   tmp_str[j] = '\0';
00291   j++;
00292 
00293   rc = my_atoi(tmp_str);
00294   if(rc == -1)
00295     return (time_t) - 1;
00296 
00297   time_struct.tm_mon = rc - 1;
00298 
00299 /*  printf("Month: %d\n",rc);*/
00300 
00301   /* parsing day of month */
00302 
00303   j = 0;
00304   for(i = 6; i < 8; i++)
00305     {
00306       if(!str[i])
00307         return (time_t) - 1;
00308       tmp_str[j] = str[i];
00309       j++;
00310     }
00311   tmp_str[j] = '\0';
00312   j++;
00313 
00314   rc = my_atoi(tmp_str);
00315   if(rc == -1)
00316     return (time_t) - 1;
00317 
00318   time_struct.tm_mday = rc;
00319 
00320 /*  printf("Day: %d\n",rc);*/
00321 
00322   /* parsing hour */
00323 
00324   j = 0;
00325   for(i = 8; i < 10; i++)
00326     {
00327       if(!str[i])
00328         return (time_t) - 1;
00329       tmp_str[j] = str[i];
00330       j++;
00331     }
00332   tmp_str[j] = '\0';
00333   j++;
00334 
00335   rc = my_atoi(tmp_str);
00336   if(rc == -1)
00337     return (time_t) - 1;
00338 
00339   time_struct.tm_hour = rc;
00340 
00341 /*  printf("Hour: %d\n",rc);*/
00342 
00343   /* parsing minute */
00344 
00345   j = 0;
00346   for(i = 10; i < 12; i++)
00347     {
00348       if(!str[i])
00349         return (time_t) - 1;
00350       tmp_str[j] = str[i];
00351       j++;
00352     }
00353   tmp_str[j] = '\0';
00354   j++;
00355 
00356   rc = my_atoi(tmp_str);
00357   if(rc == -1)
00358     return (time_t) - 1;
00359 
00360   time_struct.tm_min = rc;
00361 
00362 /*  printf("Min: %d\n",rc);*/
00363 
00364   /* parsing seconds */
00365 
00366   j = 0;
00367   for(i = 12; i < 14; i++)
00368     {
00369       if(!str[i])
00370         return (time_t) - 1;
00371       tmp_str[j] = str[i];
00372       j++;
00373     }
00374   tmp_str[j] = '\0';
00375   j++;
00376 
00377   rc = my_atoi(tmp_str);
00378   if(rc == -1)
00379     return (time_t) - 1;
00380 
00381   time_struct.tm_sec = rc;
00382 
00383 /*  printf("Sec: %d\n",rc);*/
00384 
00385   /* too many char */
00386   if(str[i])
00387     return (time_t) - 1;
00388 
00389   /* actively determines whether it is daylight time or not. */
00390   time_struct.tm_isdst = -1;
00391 
00392   return mktime(&time_struct);
00393 
00394 }
00395 
00405 static char STR_ROOT_PATH[] = "/";
00406 static char CURR_PATH[] = ".";
00407 
00408 void split_path(char *in_path, char **p_path, char **p_file)
00409 {
00410 
00411   size_t len, index;
00412 
00413   /* sanity check */
00414   if(!in_path || !p_path || !p_file)
00415     return;
00416 
00417   len = strlen(in_path);
00418 
00419   /* If the length is not 1 and the last char is '/' we remove it. */
00420 
00421   while((len > 1) && (in_path[len - 1] == '/'))
00422     {
00423       in_path[len - 1] = '\0';
00424       len--;
00425     }
00426 
00427   /* Now, we look for the last '/', if any. */
00428 
00429   index = len - 1;
00430   while((index > 0) && (in_path[index] != '/'))
00431     {
00432       index--;
00433     }
00434 
00435   /* possible cases :
00436    * /toto
00437    * xxx/toto
00438    * toto
00439    */
00440 
00441   if((index == 0) && (in_path[index] == '/'))
00442     {
00443 
00444       /* '/' is the first char */
00445       *p_path = STR_ROOT_PATH;
00446       *p_file = in_path + index + 1;
00447       return;
00448 
00449     }
00450   else if(in_path[index] == '/')
00451     {
00452 
00453       in_path[index] = '\0';
00454       *p_path = in_path;
00455       *p_file = in_path + index + 1;
00456       return;
00457 
00458     }
00459   else if(index == 0)
00460     {
00461 
00462       /* no '/' found */
00463       *p_path = CURR_PATH;
00464       *p_file = in_path;
00465       return;
00466 
00467     }
00468 
00469 }
00470 
00471 /* Time formatting routine */
00472 char *time2str(time_t time_in, char *str_out)
00473 {
00474 
00475 #define TIME_STRLEN 30
00476 
00477   struct tm paramtm;
00478   time_t now;                   /* Now  */
00479   time_t jan_1;                 /* 01/01 of the current year */
00480 
00481   /*inits 'jan_1' for date printing */
00482   time(&now);
00483   Localtime_r(&now, &paramtm);
00484   paramtm.tm_mon = 0;
00485   paramtm.tm_mday = 1;
00486   paramtm.tm_hour = 1;
00487   paramtm.tm_min = 0;
00488   paramtm.tm_sec = 1;
00489   jan_1 = mktime(&paramtm);
00490 
00491   if(time_in < jan_1)
00492     {                           /* if dates back to last year : MM dd YYYY */
00493       strftime(str_out, TIME_STRLEN, "%b %e %Y ", Localtime_r(&time_in, &paramtm));
00494     }
00495   else
00496     {                           /* MM dd hh:mm */
00497       strftime(str_out, TIME_STRLEN, "%b %e %R", Localtime_r(&time_in, &paramtm));
00498     }
00499   return str_out;
00500 
00501 }
00502 
00513 void clean_path(char *str, int len)
00514 {
00515 
00516   int indexsrc = 0;
00517   int indexdest = 0;
00518 
00519   int length;
00520 
00521   char *sdd_index;              /* "slash dot dot" index */
00522   char *slash_index;            /* previous slash index */
00523 
00524   /* removes double slashes */
00525     /**************************/
00526   while(str[indexsrc] && (indexsrc + 1 < len))
00527     {
00528       while((indexsrc + 1 < len) && (str[indexsrc] == '/') && (str[indexsrc + 1] == '/'))
00529         indexsrc++;
00530       str[indexdest++] = str[indexsrc++];
00531     }
00532   if(!str[indexsrc])
00533     str[indexdest] = str[indexsrc];
00534 
00535   /* removes '/./' and '/.\0' */
00536     /****************************/
00537 
00538   /* if the path ends with /., we add a slash at the end,
00539      so '/./' will be detected in the next loop. */
00540 #ifdef _TOTO
00541   length = strlen(str);
00542   if(length >= 2)
00543     {
00544       if((str[length - 1] == '.') && (str[length - 2] == '/'))
00545         {
00546           str[length] = '/';
00547           str[length + 1] = '\0';
00548         }
00549     }
00550 #endif
00551 
00552   /* detects and removes '/./' */
00553 
00554   sdd_index = (char *)strstr(str, "/./");
00555   while(sdd_index)
00556     {
00557 
00558       /* we copy everything after "/./" to sdd_index */
00559       indexsrc = 3;             /* index in sdd_index */
00560       indexdest = 1;            /* index in sdd_index */
00561       /* BUG: I'm pretty sure this can't be right???? */
00562       while((sdd_index[indexdest] = sdd_index[indexsrc]))
00563         {
00564           indexdest++;
00565           indexsrc++;
00566         }
00567 
00568       /* inits the next loop */
00569       sdd_index = (char *)strstr(str, "/./");
00570     }
00571 
00572   /* removes '/../' and '/..\0' */
00573     /******************************/
00574 
00575   /* if the path ends with /.., we add a slash at the end,
00576      so '/../' will be detected in the next loop. */
00577   length = strlen(str);
00578   if(length >= 3)
00579     {
00580       if((str[length - 1] == '.') && (str[length - 2] == '.') && (str[length - 3] == '/'))
00581         {
00582           str[length] = '/';
00583           str[length + 1] = '\0';
00584         }
00585     }
00586 
00587   /* detects and removes '/../' */
00588 
00589   sdd_index = (char *)strstr(str, "/../");
00590 
00591   while(sdd_index)
00592     {
00593 
00594       /* look for the first '/' that preceeds sdd_index */
00595       for(slash_index = sdd_index - 1; (slash_index >= str) && (slash_index[0] != '/');
00596           slash_index--) ;
00597 
00598       /* if found, removes rep/../ path */
00599 
00600       if((slash_index[0] == '/') && (slash_index >= str))
00601         {
00602 
00603           /* we copy everything after "/../" to slash_index */
00604           indexsrc = 4;         /* index in sdd_index */
00605           indexdest = 1;        /* index in slash_index */
00606           while((slash_index[indexdest] = sdd_index[indexsrc]))
00607             {
00608               indexdest++;
00609               indexsrc++;
00610             }
00611 
00612         }
00613       else
00614         {
00615 
00616           /* if not found, it is '..' on the root directory. */
00617 
00618           /* If the path begins with a filehandle,
00619              we replace @handle/../ by @handle/..> */
00620 
00621           if(str[0] == '@')
00622             {
00623 
00624               sdd_index[3] = '>';
00625 
00626             }
00627           else
00628             {
00629               /* Else , we remove '/..' */
00630 
00631               indexsrc = 3;     /* index in str */
00632               indexdest = 0;    /* index in str */
00633               while((str[indexdest] = str[indexsrc]))
00634                 {
00635                   indexdest++;
00636                   indexsrc++;
00637                 }
00638 
00639             }                   /* end @ */
00640 
00641         }
00642       /* inits the next loop */
00643       sdd_index = (char *)strstr(str, "/../");
00644     }
00645 
00646   /* removes final slash */
00647     /***********************/
00648   length = strlen(str);
00649   if(length > 1)
00650     {
00651       if(str[length - 1] == '/')
00652         str[length - 1] = '\0';
00653     }
00654 
00655 }
00656 
00666 void print_fsal_status(FILE * output, fsal_status_t status)
00667 {
00668 
00669   char _str_[256];
00670 
00671 #ifdef _USE_GHOSTFS
00672 
00673   log_snprintf(_str_, 256, "%J%r,%J%r",
00674                ERR_FSAL, status.major, ERR_GHOSTFS, status.minor);
00675 
00676 #else
00677 
00678   log_snprintf(_str_, 256, "%J%r, filesystem status: %d",
00679                ERR_FSAL, status.major, status.minor);
00680 
00681 #endif
00682 
00683   fprintf(output, "%s", _str_);
00684 }
00685 
00695 void fsal_status_to_string(char * output, fsal_status_t status)
00696 {
00697 
00698 #ifdef _USE_GHOSTFS
00699 
00700   log_snprintf(output, sizeof(output), "%J%r,%J%r",
00701                ERR_FSAL, status.major, ERR_GHOSTFS, status.minor);
00702 
00703 #else
00704 
00705   log_snprintf(output, sizeof(output), "%J%r, filesystem status: %d",
00706                ERR_FSAL, status.major, status.minor);
00707 
00708 #endif
00709 }
00710 
00711 
00720 void print_fsal_attrib_mask(fsal_attrib_mask_t mask, FILE * output)
00721 {
00722 
00723   if(FSAL_TEST_MASK(mask, FSAL_ATTR_SUPPATTR))
00724     fprintf(output, "\tFSAL_ATTR_SUPPATTR\n");
00725   if(FSAL_TEST_MASK(mask, FSAL_ATTR_TYPE))
00726     fprintf(output, "\tFSAL_ATTR_TYPE\n");
00727   if(FSAL_TEST_MASK(mask, FSAL_ATTR_SIZE))
00728     fprintf(output, "\tFSAL_ATTR_SIZE\n");
00729   if(FSAL_TEST_MASK(mask, FSAL_ATTR_FSID))
00730     fprintf(output, "\tFSAL_ATTR_FSID\n");
00731   if(FSAL_TEST_MASK(mask, FSAL_ATTR_ACL))
00732     fprintf(output, "\tFSAL_ATTR_ACL \n");
00733   if(FSAL_TEST_MASK(mask, FSAL_ATTR_FILEID))
00734     fprintf(output, "\tFSAL_ATTR_FILEID\n");
00735   if(FSAL_TEST_MASK(mask, FSAL_ATTR_MODE))
00736     fprintf(output, "\tFSAL_ATTR_MODE\n");
00737   if(FSAL_TEST_MASK(mask, FSAL_ATTR_NUMLINKS))
00738     fprintf(output, "\tFSAL_ATTR_NUMLINKS\n");
00739   if(FSAL_TEST_MASK(mask, FSAL_ATTR_OWNER))
00740     fprintf(output, "\tFSAL_ATTR_OWNER\n");
00741   if(FSAL_TEST_MASK(mask, FSAL_ATTR_GROUP))
00742     fprintf(output, "\tFSAL_ATTR_GROUP\n");
00743   if(FSAL_TEST_MASK(mask, FSAL_ATTR_RAWDEV))
00744     fprintf(output, "\tFSAL_ATTR_RAWDEV\n");
00745   if(FSAL_TEST_MASK(mask, FSAL_ATTR_ATIME))
00746     fprintf(output, "\tFSAL_ATTR_ATIME\n");
00747   if(FSAL_TEST_MASK(mask, FSAL_ATTR_CREATION))
00748     fprintf(output, "\tFSAL_ATTR_CREATION\n");
00749   if(FSAL_TEST_MASK(mask, FSAL_ATTR_CTIME))
00750     fprintf(output, "\tFSAL_ATTR_CTIME\n");
00751   if(FSAL_TEST_MASK(mask, FSAL_ATTR_MTIME))
00752     fprintf(output, "\tFSAL_ATTR_MTIME\n");
00753   if(FSAL_TEST_MASK(mask, FSAL_ATTR_SPACEUSED))
00754     fprintf(output, "\tFSAL_ATTR_SPACEUSED\n");
00755   if(FSAL_TEST_MASK(mask, FSAL_ATTR_MOUNTFILEID))
00756     fprintf(output, "\tFSAL_ATTR_MOUNTFILEID\n");
00757 
00758 }
00759 
00767 char *strtype(fsal_nodetype_t type)
00768 {
00769   switch (type)
00770     {
00771     case FSAL_TYPE_FIFO:
00772       return "FSAL_TYPE_FIFO ";
00773     case FSAL_TYPE_CHR:
00774       return "FSAL_TYPE_CHR  ";
00775     case FSAL_TYPE_DIR:
00776       return "FSAL_TYPE_DIR  ";
00777     case FSAL_TYPE_BLK:
00778       return "FSAL_TYPE_BLK  ";
00779     case FSAL_TYPE_FILE:
00780       return "FSAL_TYPE_FILE ";
00781     case FSAL_TYPE_LNK:
00782       return "FSAL_TYPE_LNK  ";
00783     case FSAL_TYPE_JUNCTION:
00784       return "FSAL_TYPE_JUNCTION  ";
00785     default:
00786       return "Unknown type   ";
00787     }
00788 }
00789 
00798 void print_fsal_attributes(fsal_attrib_list_t attrs, FILE * output)
00799 {
00800 
00801   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_TYPE))
00802     fprintf(output, "\tType : %s\n", strtype(attrs.type));
00803   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_SIZE))
00804     fprintf(output, "\tSize : %llu\n", attrs.filesize);
00805   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_FSID))
00806     fprintf(output, "\tfsId : %llu.%llu\n", attrs.fsid.major, attrs.fsid.minor);
00807   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ACL))
00808     fprintf(output, "\tACL List : (printing not implemented)\n");
00809   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_FILEID))
00810     fprintf(output, "\tFileId : %#llx\n", attrs.fileid);
00811   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00812     fprintf(output, "\tMode : %#o\n", attrs.mode);
00813   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_NUMLINKS))
00814     fprintf(output, "\tNumlinks : %u\n", (unsigned int)attrs.numlinks);
00815   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
00816     fprintf(output, "\tuid : %d\n", attrs.owner);
00817   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
00818     fprintf(output, "\tgid : %d\n", attrs.group);
00819   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_RAWDEV))
00820     fprintf(output, "\tRawdev ...\n");
00821   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME))
00822     fprintf(output, "\tatime : %s", ctime((time_t *) & attrs.atime.seconds));
00823   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CREATION))
00824     fprintf(output, "\tcreation time : %s", ctime((time_t *) & attrs.creation.seconds));
00825   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CTIME))
00826     fprintf(output, "\tctime : %s", ctime((time_t *) & attrs.ctime.seconds));
00827   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME))
00828     fprintf(output, "\tmtime : %s", ctime((time_t *) & attrs.mtime.seconds));
00829   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_SPACEUSED))
00830     fprintf(output, "\tspaceused : %llu\n", attrs.spaceused);
00831   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MOUNTFILEID))
00832     fprintf(output, "\tmounted_on_fileid : %#llx\n", attrs.mounted_on_fileid);
00833 
00834 }
00835 
00848 #define print_mask(_out,_mode,_mask,_lettre) do {    \
00849         if (_mode & _mask) fprintf(_out,_lettre);\
00850         else fprintf(_out,"-");                  \
00851       } while(0)
00852 
00853 void print_item_line(FILE * out, fsal_attrib_list_t * attrib, char *name, char *target)
00854 {
00855 
00856   char buff[256];
00857 
00858   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_FILEID))
00859     {
00860       /* print inode */
00861       fprintf(out, "%10llx ", attrib->fileid);
00862     }
00863 
00864   /* printing type (mandatory) */
00865   switch (attrib->type)
00866     {
00867     case FSAL_TYPE_FIFO:
00868       fprintf(out, "p");
00869       break;
00870     case FSAL_TYPE_CHR:
00871       fprintf(out, "c");
00872       break;
00873     case FSAL_TYPE_DIR:
00874       fprintf(out, "d");
00875       break;
00876     case FSAL_TYPE_BLK:
00877       fprintf(out, "b");
00878       break;
00879     case FSAL_TYPE_FILE:
00880       fprintf(out, "-");
00881       break;
00882     case FSAL_TYPE_LNK:
00883       fprintf(out, "l");
00884       break;
00885     case FSAL_TYPE_JUNCTION:
00886       fprintf(out, "j");
00887       break;
00888     default:
00889       fprintf(out, "?");
00890     }
00891 
00892   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_MODE))
00893     {
00894 
00895       /* printing rights */
00896       print_mask(out, attrib->mode, FSAL_MODE_RUSR, "r");
00897       print_mask(out, attrib->mode, FSAL_MODE_WUSR, "w");
00898 
00899       if(attrib->mode & FSAL_MODE_SUID)
00900         {
00901           if(attrib->mode & FSAL_MODE_XUSR)
00902             fprintf(out, "s");
00903           else
00904             fprintf(out, "S");
00905         }
00906       else
00907         {
00908           if(attrib->mode & FSAL_MODE_XUSR)
00909             fprintf(out, "x");
00910           else
00911             fprintf(out, "-");
00912         }
00913 
00914       print_mask(out, attrib->mode, FSAL_MODE_RGRP, "r");
00915       print_mask(out, attrib->mode, FSAL_MODE_WGRP, "w");
00916 
00917       if(attrib->mode & FSAL_MODE_SGID)
00918         {
00919           if(attrib->mode & FSAL_MODE_XGRP)
00920             fprintf(out, "s");
00921           else
00922             fprintf(out, "l");
00923         }
00924       else
00925         {
00926           if(attrib->mode & FSAL_MODE_XGRP)
00927             fprintf(out, "x");
00928           else
00929             fprintf(out, "-");
00930         }
00931       print_mask(out, attrib->mode, FSAL_MODE_ROTH, "r");
00932       print_mask(out, attrib->mode, FSAL_MODE_WOTH, "w");
00933       print_mask(out, attrib->mode, FSAL_MODE_XOTH, "x");
00934     }
00935 
00936   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_NUMLINKS))
00937     {
00938       /* print linkcount */
00939       fprintf(out, " %3u", (unsigned int)attrib->numlinks);
00940     }
00941 
00942   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_OWNER))
00943     {
00944       /* print uid */
00945       fprintf(out, " %8d", attrib->owner);
00946     }
00947 
00948   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_GROUP))
00949     {
00950       /* print gid */
00951       fprintf(out, " %8d", attrib->group);
00952     }
00953 
00954   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_SIZE))
00955     {
00956       /* print size */
00957       fprintf(out, " %15llu", attrib->filesize);
00958     }
00959 
00960   if(FSAL_TEST_MASK(attrib->asked_attributes, FSAL_ATTR_MTIME))
00961     {
00962       /* print mtime */
00963       fprintf(out, " %15s", time2str(attrib->mtime.seconds, buff));
00964     }
00965 
00966   /* print name */
00967   fprintf(out, " %s", name);
00968 
00969   if(attrib->type == FSAL_TYPE_LNK)
00970     fprintf(out, " -> %s", target);
00971 
00972   fprintf(out, "\n");
00973   return;
00974 
00975 }
00976 
00983 int MkFSALSetAttrStruct(char *attribute_list, fsal_attrib_list_t * fsal_set_attr_struct)
00984 {
00985   shell_attribute_t *current_attr;
00986   char attrib_list_tmp[2048];
00987 
00988   char *attrib_str;
00989   char *value_str;
00990   char *next_str = NULL;
00991 
00992   int rc;
00993 
00994   int param_32;
00995   unsigned long long param_64;
00996   time_t param_time;
00997 
00998   int *p_32;
00999   unsigned long long *p_64;
01000   time_t *p_time;
01001 
01002   /* sanity checks */
01003 
01004   if(!attribute_list || !fsal_set_attr_struct)
01005     return EFAULT;
01006 
01007   /* init output struct */
01008 
01009   memset(fsal_set_attr_struct, 0, sizeof(fsal_attrib_list_t));
01010 
01011   /* set attribute mask */
01012 
01013   FSAL_CLEAR_MASK(fsal_set_attr_struct->asked_attributes);
01014 
01015   /* temporary copy the attribute list */
01016   strncpy(attrib_list_tmp, attribute_list, 2048);
01017   attrib_list_tmp[2047] = '\0';
01018 
01019   /* get the first token */
01020   attrib_str = strtok_r(attrib_list_tmp, ",", &next_str);
01021 
01022   if(attrib_str == NULL)
01023     return EINVAL;
01024 
01025   while(attrib_str != NULL)
01026     {
01027       /* retrieving attribute value */
01028       attrib_str = strtok_r(attrib_str, "=", &value_str);
01029 
01030       if((attrib_str == NULL) || (value_str == NULL))
01031         return EINVAL;
01032 
01033       printf("Attribute: \"%s\", Value: \"%s\"\n", attrib_str, value_str);
01034 
01035       /* look for the attribute to be set. */
01036 
01037       for(current_attr = shell_attr_list;
01038           current_attr->attr_type != ATTR_NONE; current_attr++)
01039         {
01040 
01041           if(!strcasecmp(current_attr->attr_name, attrib_str))
01042             {
01043 
01044               /* exists loop */
01045               break;
01046             }
01047 
01048         }
01049 
01050       /* attribute not found */
01051 
01052       if(current_attr->attr_type == ATTR_NONE)
01053         return ENOENT;
01054 
01055       FSAL_SET_MASK(fsal_set_attr_struct->asked_attributes, current_attr->attr_mask);
01056 
01057       /* convert the attribute value to the correct type */
01058 
01059       switch (current_attr->attr_type)
01060         {
01061         case ATTR_32:
01062 
01063           param_32 = my_atoi(value_str);
01064           if(param_32 == -1)
01065             return EINVAL;
01066           p_32 = (int *)((caddr_t) fsal_set_attr_struct + current_attr->attr_offset);
01067 
01068           *p_32 = param_32;
01069 
01070           break;
01071 
01072         case ATTR_64:
01073 
01074           rc = ato64(value_str, &param_64);
01075           if(rc == -1)
01076             return EINVAL;
01077           p_64 =
01078               (unsigned long long *)((caddr_t) fsal_set_attr_struct +
01079                                      current_attr->attr_offset);
01080 
01081           *p_64 = param_64;
01082 
01083           break;
01084 
01085         case ATTR_OCTAL:       /* only for modes */
01086 
01087           param_32 = atomode(value_str);
01088           if(param_32 == -1)
01089             return EINVAL;
01090           p_32 = (int *)((caddr_t) fsal_set_attr_struct + current_attr->attr_offset);
01091 
01092           *p_32 = unix2fsal_mode(param_32);
01093 
01094           break;
01095 
01096         case ATTR_TIME:
01097 
01098           param_time = atotime(value_str);
01099           if(param_time == (time_t) - 1)
01100             return EINVAL;
01101           p_time =
01102               (time_t *) ((caddr_t) fsal_set_attr_struct + current_attr->attr_offset);
01103 
01104           *p_time = param_time;
01105 
01106           break;
01107         default:
01108           break;
01109         }
01110 
01111       /* now process the next attribute */
01112 
01113       attrib_str = next_str;
01114 
01115       next_str = NULL;          /* paranoid setting */
01116       value_str = NULL;         /* paranoid setting */
01117 
01118       if(attrib_str != NULL)
01119         attrib_str = strtok_r(attrib_str, ",", &next_str);
01120 
01121     }
01122 
01123   /* OK */
01124   return 0;
01125 
01126 }
01127 
01128 /* timer diffing function */
01129 
01130 struct timeval time_diff(struct timeval time_from, struct timeval time_to)
01131 {
01132 
01133   struct timeval result;
01134 
01135   if(time_to.tv_usec < time_from.tv_usec)
01136     {
01137       result.tv_sec = time_to.tv_sec - time_from.tv_sec - 1;
01138       result.tv_usec = 1000000 + time_to.tv_usec - time_from.tv_usec;
01139     }
01140   else
01141     {
01142       result.tv_sec = time_to.tv_sec - time_from.tv_sec;
01143       result.tv_usec = time_to.tv_usec - time_from.tv_usec;
01144     }
01145 
01146   return result;
01147 
01148 }
01149 
01150 /* used for concatenation in set */
01151 
01152 char *concat(char *str1, char *str2, size_t max_len)
01153 {
01154   size_t len1, len2;
01155 
01156   len1 = strlen(str1);
01157   len2 = strlen(str2);
01158 
01159   if(len1 + len2 + 1 > max_len)
01160     return NULL;
01161 
01162   return strcat(str1, str2);
01163 
01164 }
01165 
01166 /* Inspired from Free Software Foundation code. */
01167 int getugroups(int maxcount, gid_t * grouplist, char *username, gid_t gid)
01168 {
01169   struct group *grp;
01170   register char **cp;
01171   register int count = 0;
01172 
01173   if(gid != (gid_t) - 1)
01174     {
01175       if(maxcount != 0)
01176         grouplist[count] = gid;
01177 
01178       count++;
01179     }
01180 
01181   setgrent();
01182   while((grp = getgrent()) != 0)
01183     {
01184       for(cp = grp->gr_mem; *cp; ++cp)
01185         {
01186           int n;
01187 
01188           if(strcmp(username, *cp))
01189             continue;
01190 
01191           /* see if this group number is already in the list */
01192           for(n = 0; n < count; ++n)
01193             if(grouplist && grouplist[n] == grp->gr_gid)
01194               break;
01195 
01196           /* add the group to the list */
01197           if(n == count)
01198             {
01199               if(maxcount != 0)
01200                 {
01201                   if(count >= maxcount)
01202                     {
01203                       endgrent();
01204                       return count;
01205                     }
01206                   grouplist[count] = grp->gr_gid;
01207 
01208                 }
01209               count++;
01210             }
01211 
01212         }
01213     }
01214   endgrent();
01215 
01216   return count;
01217 }