nfs-ganesha 1.4
|
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, ¶mtm); 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(¶mtm); 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, ¶mtm)); 00494 } 00495 else 00496 { /* MM dd hh:mm */ 00497 strftime(str_out, TIME_STRLEN, "%b %e %R", Localtime_r(&time_in, ¶mtm)); 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, ¶m_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 }