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 00036 #ifdef HAVE_CONFIG_H 00037 #include "config.h" 00038 #endif 00039 00040 #ifdef _SOLARIS 00041 #include "solaris_port.h" 00042 #endif 00043 00044 #include <stdio.h> 00045 #include <string.h> 00046 #include <pthread.h> 00047 #include <fcntl.h> 00048 #include <sys/file.h> /* for having FNDELAY */ 00049 #include "HashData.h" 00050 #include "HashTable.h" 00051 #include "log.h" 00052 #include "ganesha_rpc.h" 00053 #include "nfs4.h" 00054 #include "nfs_core.h" 00055 #include "nfs_proto_functions.h" 00056 #include "nfs_tools.h" 00057 #include "nfs_exports.h" 00058 #include "nfs_file_handle.h" 00059 #include "cache_inode.h" 00060 00061 #define NB_TOK_ARG 10 00062 #define NB_OPT_TOK 10 00063 #define NB_TOK_PATH 20 00064 00065 static pseudofs_t gPseudoFs; 00066 00081 uint64_t nfs4_PseudoToId(nfs_fh4 * fh4p) 00082 { 00083 file_handle_v4_t *pfhandle4; 00084 uint64_t out = 0LL; 00085 00086 pfhandle4 = (file_handle_v4_t *) (fh4p->nfs_fh4_val); 00087 00088 out = (uint64_t) (pfhandle4->pseudofs_id); 00089 return out; 00090 } /* nfs4_PseudoToId */ 00091 00101 pseudofs_t *nfs4_GetPseudoFs(void) 00102 { 00103 return &gPseudoFs; 00104 } /* nfs4_GetExportList */ 00105 00115 int nfs4_ExportToPseudoFS(exportlist_t * pexportlist) 00116 { 00117 exportlist_t *entry; 00118 exportlist_t *next; /* exportlist entry */ 00119 int i = 0; 00120 int j = 0; 00121 int found = 0; 00122 char tmp_pseudopath[MAXPATHLEN]; 00123 char *PathTok[NB_TOK_PATH]; 00124 int NbTokPath; 00125 pseudofs_t *PseudoFs = NULL; 00126 pseudofs_entry_t *PseudoFsRoot = NULL; 00127 pseudofs_entry_t *PseudoFsCurrent = NULL; 00128 pseudofs_entry_t *newPseudoFsEntry = NULL; 00129 pseudofs_entry_t *iterPseudoFs = NULL; 00130 00131 entry = pexportlist; 00132 00133 PseudoFs = &gPseudoFs; 00134 00135 /* Init Root of the Pseudo FS tree */ 00136 strncpy(PseudoFs->root.name, "/", MAXNAMLEN); 00137 strncpy(PseudoFs->root.fullname, "(nfsv4root)", MAXPATHLEN); 00138 PseudoFs->root.pseudo_id = 0; 00139 PseudoFs->root.junction_export = NULL; 00140 PseudoFs->root.next = NULL; 00141 PseudoFs->root.last = PseudoFsRoot; 00142 PseudoFs->root.sons = NULL; 00143 PseudoFs->root.parent = &(PseudoFs->root); /* root is its own parent */ 00144 00145 /* Allocation of the parsing table */ 00146 for(i = 0; i < NB_TOK_PATH; i++) 00147 if((PathTok[i] = gsh_malloc(MAXNAMLEN)) == NULL) 00148 return ENOMEM; 00149 00150 while(entry) 00151 { 00152 /* To not forget to init "/" entry */ 00153 PseudoFsCurrent = &(PseudoFs->root); 00154 PseudoFs->reverse_tab[0] = &(PseudoFs->root); 00155 00156 /* skip exports that aren't for NFS v4 */ 00157 if((entry->options & EXPORT_OPTION_NFSV4) == 0) 00158 { 00159 next = entry->next; 00160 entry = next; 00161 continue; 00162 } 00163 00164 if(entry->options & EXPORT_OPTION_PSEUDO) 00165 { 00166 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00167 "BUILDING PSEUDOFS: Id = %d", 00168 entry->id); 00169 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00170 "BUILDING PSEUDOFS: ANON = %d", 00171 entry->anonymous_uid); 00172 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00173 "BUILDING PSEUDOFS: Path = %s", 00174 entry->fullpath); 00175 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00176 "BUILDING PSEUDOFS: Options = 0x%x", 00177 entry->options); 00178 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00179 "BUILDING PSEUDOFS: Num Clients = %d", 00180 entry->clients.num_clients); 00181 00182 /* A pseudo path is to ne managed */ 00183 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00184 "BUILDING PSEUDOFS: Now managing %s seen as %s", 00185 entry->fullpath, entry->pseudopath); 00186 00187 /* Parsing the path */ 00188 strncpy(tmp_pseudopath, entry->pseudopath, MAXPATHLEN); 00189 if((NbTokPath = 00190 nfs_ParseConfLine(PathTok, NB_TOK_PATH, tmp_pseudopath, find_slash, 00191 find_endLine)) < 0) 00192 { 00193 /* Path is badly formed */ 00194 LogCrit(COMPONENT_NFS_V4_PSEUDO, 00195 "BUILDING PSEUDOFS: Invalid 'pseudo' option: %s", 00196 entry->pseudopath); 00197 next = entry->next; 00198 entry = next; 00199 continue; 00200 } 00201 00202 /* there must be a leading '/' in the pseudo path */ 00203 if(entry->pseudopath[0] != '/') 00204 { 00205 /* Path is badly formed */ 00206 LogCrit(COMPONENT_NFS_V4_PSEUDO, 00207 "Pseudo Path '%s' is badly formed", 00208 entry->pseudopath); 00209 next = entry->next; 00210 entry = next; 00211 continue; 00212 } 00213 00214 /* Loop on each token. Because first character in pseudo path is '/' 00215 * we can avoid looking at PathTok[0] which is necessary '\0'. That's 00216 * the reason why we start looping at pos = 1 */ 00217 for(j = 1; j < NbTokPath; j++) 00218 LogFullDebug(COMPONENT_NFS_V4, " tokens are #%s#", PathTok[j]); 00219 00220 for(j = 1; j < NbTokPath; j++) 00221 { 00222 found = 0; 00223 for(iterPseudoFs = PseudoFsCurrent->sons; iterPseudoFs != NULL; 00224 iterPseudoFs = iterPseudoFs->next) 00225 { 00226 /* Looking for a matching entry */ 00227 if(!strcmp(iterPseudoFs->name, PathTok[j])) 00228 { 00229 found = 1; 00230 break; 00231 } 00232 } /* for iterPseudoFs */ 00233 00234 if(found) 00235 { 00236 /* a matching entry was found in the tree */ 00237 PseudoFsCurrent = iterPseudoFs; 00238 } 00239 else 00240 { 00241 /* a new entry is to be created */ 00242 if((newPseudoFsEntry = 00243 gsh_malloc(sizeof(pseudofs_entry_t))) == NULL) 00244 return ENOMEM; 00245 00246 /* Creating the new entry, allocate an id for it and add it to reverse tab */ 00247 strncpy(newPseudoFsEntry->name, PathTok[j], MAXNAMLEN); 00248 newPseudoFsEntry->pseudo_id = PseudoFs->last_pseudo_id + 1; 00249 PseudoFs->last_pseudo_id = newPseudoFsEntry->pseudo_id; 00250 PseudoFs->reverse_tab[PseudoFs->last_pseudo_id] = newPseudoFsEntry; 00251 newPseudoFsEntry->junction_export = NULL; 00252 newPseudoFsEntry->last = newPseudoFsEntry; 00253 newPseudoFsEntry->next = NULL; 00254 newPseudoFsEntry->sons = NULL; 00255 snprintf(newPseudoFsEntry->fullname, MAXPATHLEN, "%s/%s", 00256 PseudoFsCurrent->fullname, PathTok[j]); 00257 00258 /* Step into the new entry and attach it to the tree */ 00259 if(PseudoFsCurrent->sons == NULL) 00260 PseudoFsCurrent->sons = newPseudoFsEntry; 00261 else 00262 { 00263 PseudoFsCurrent->sons->last->next = newPseudoFsEntry; 00264 PseudoFsCurrent->sons->last = newPseudoFsEntry; 00265 } 00266 newPseudoFsEntry->parent = PseudoFsCurrent; 00267 PseudoFsCurrent = newPseudoFsEntry; 00268 } 00269 00270 } /* for j */ 00271 00272 /* Now that all entries are added to pseudofs tree, add the junction to the pseudofs */ 00273 PseudoFsCurrent->junction_export = entry; 00274 00275 } 00276 /* if( entry->options & EXPORT_OPTION_PSEUDO ) */ 00277 next = entry->next; 00278 00279 entry = next; 00280 } /* while( entry ) */ 00281 00282 /* desalocation of the parsing table */ 00283 for(i = 0; i < NB_TOK_PATH; i++) 00284 gsh_free(PathTok[i]); 00285 00286 return (0); 00287 } 00288 00304 int nfs4_PseudoToFattr(pseudofs_entry_t * psfsp, 00305 fattr4 * Fattr, 00306 compound_data_t * data, nfs_fh4 * objFH, bitmap4 * Bitmap) 00307 { 00308 fattr4_type file_type; 00309 fattr4_link_support link_support; 00310 fattr4_symlink_support symlink_support; 00311 fattr4_fh_expire_type expire_type; 00312 fattr4_named_attr named_attr; 00313 fattr4_unique_handles unique_handles; 00314 fattr4_archive archive; 00315 fattr4_cansettime cansettime; 00316 fattr4_case_insensitive case_insensitive; 00317 fattr4_case_preserving case_preserving; 00318 fattr4_chown_restricted chown_restricted; 00319 fattr4_hidden hidden; 00320 fattr4_mode file_mode; 00321 fattr4_no_trunc no_trunc; 00322 fattr4_numlinks file_numlinks; 00323 fattr4_rawdev rawdev; 00324 fattr4_system system; 00325 fattr4_size file_size; 00326 fattr4_space_used file_space_used; 00327 fattr4_fsid fsid; 00328 fattr4_time_access time_access; 00329 fattr4_time_modify time_modify; 00330 fattr4_time_metadata time_metadata; 00331 fattr4_time_delta time_delta; 00332 fattr4_time_backup time_backup; 00333 fattr4_time_create time_create; 00334 fattr4_change file_change; 00335 fattr4_fileid file_id; 00336 fattr4_owner file_owner; 00337 fattr4_owner_group file_owner_group; 00338 fattr4_space_avail space_avail; 00339 fattr4_space_free space_free; 00340 fattr4_space_total space_total; 00341 fattr4_files_avail files_avail; 00342 fattr4_files_free files_free; 00343 fattr4_files_total files_total; 00344 fattr4_lease_time lease_time; 00345 fattr4_maxfilesize max_filesize; 00346 fattr4_maxread maxread; 00347 fattr4_maxwrite maxwrite; 00348 fattr4_maxname maxname; 00349 fattr4_maxlink maxlink; 00350 fattr4_homogeneous homogeneous; 00351 fattr4_acl acl; 00352 fattr4_mimetype mimetype; 00353 fattr4_aclsupport aclsupport; 00354 fattr4_quota_avail_hard quota_avail_hard; 00355 fattr4_quota_avail_soft quota_avail_soft; 00356 fattr4_quota_used quota_used; 00357 fattr4_mounted_on_fileid mounted_on_fileid; 00358 #ifdef _USE_NFS4_1 00359 fattr4_fs_layout_types layout_types; 00360 layouttype4 layouts[1]; 00361 #endif 00362 00363 u_int fhandle_len = 0; 00364 unsigned int LastOffset; 00365 unsigned int len = 0, off = 0; /* Use for XDR alignment */ 00366 int op_attr_success = 0; 00367 unsigned int i = 0; 00368 unsigned int j = 0; 00369 unsigned int attrmasklen = 0; 00370 unsigned int attribute_to_set = 0; 00371 00372 #ifdef _USE_NFS4_1 00373 unsigned int attrmasklist[FATTR4_FS_CHARSET_CAP]; /* List cannot be longer than FATTR4_FS_CHARSET_CAP */ 00374 unsigned int attrvalslist[FATTR4_FS_CHARSET_CAP]; /* List cannot be longer than FATTR4_FS_CHARSET_CAP */ 00375 #else 00376 unsigned int attrmasklist[FATTR4_MOUNTED_ON_FILEID]; /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */ 00377 unsigned int attrvalslist[FATTR4_MOUNTED_ON_FILEID]; /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */ 00378 #endif 00379 char attrvalsBuffer[ATTRVALS_BUFFLEN]; 00380 00381 char __attribute__ ((__unused__)) funcname[] = "nfs4_PseudoToFattr"; 00382 00383 /* memset to make sure the arrays are initiated to 0 */ 00384 memset(attrvalsBuffer, 0, NFS4_ATTRVALS_BUFFLEN); 00385 #ifdef _USE_NFS4_1 00386 memset((uint32_t *) attrmasklist, 0, FATTR4_FS_CHARSET_CAP * sizeof(uint32_t)); 00387 memset((uint32_t *) attrvalslist, 0, FATTR4_FS_CHARSET_CAP * sizeof(uint32_t)); 00388 #else 00389 memset((uint32_t *) attrmasklist, 0, FATTR4_MOUNTED_ON_FILEID * sizeof(uint32_t)); 00390 memset((uint32_t *) attrvalslist, 0, FATTR4_MOUNTED_ON_FILEID * sizeof(uint32_t)); 00391 #endif 00392 00393 /* Convert the attribute bitmap to an attribute list */ 00394 nfs4_bitmap4_to_list(Bitmap, &attrmasklen, attrmasklist); 00395 00396 /* Once the bitmap has been converted to a list of attribute, manage each attribute */ 00397 Fattr->attr_vals.attrlist4_len = 0; 00398 LastOffset = 0; 00399 j = 0; 00400 00401 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00402 "Asked Attributes (Pseudo): Bitmap = (len=%d, val[0]=%d, val[1]=%d), %d item in list", 00403 Bitmap->bitmap4_len, Bitmap->bitmap4_val[0], 00404 Bitmap->bitmap4_val[1], attrmasklen); 00405 00406 if(attrmasklen == 0) 00407 { 00408 Bitmap->bitmap4_len = 0; 00409 Bitmap->bitmap4_val = 0; 00410 return 0; /* Nothing to be done */ 00411 } 00412 00413 for(i = 0; i < attrmasklen; i++) 00414 { 00415 attribute_to_set = attrmasklist[i]; 00416 00417 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00418 "Flag for Operation (Pseudo) = %d|%d is ON, name = %s reply_size = %d supported = %d", 00419 attrmasklist[i], fattr4tab[attribute_to_set].val, 00420 fattr4tab[attribute_to_set].name, 00421 fattr4tab[attribute_to_set].size_fattr4, 00422 fattr4tab[attribute_to_set].supported); 00423 00424 op_attr_success = 0; 00425 00426 /* compute the new size for the fattr4 reply */ 00427 /* This space is to be filled below in the big switch/case statement */ 00428 00429 switch (attribute_to_set) 00430 { 00431 case FATTR4_SUPPORTED_ATTRS: 00432 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00433 "-----> Wanting FATTR4_SUPPORTED_ATTRS"); 00434 00435 LastOffset += nfs4_supported_attrs_to_fattr(attrvalsBuffer+LastOffset); 00436 00437 /* This kind of operation is always a success */ 00438 op_attr_success = 1; 00439 break; 00440 00441 case FATTR4_TYPE: 00442 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00443 "-----> Wanting FATTR4_TYPE"); 00444 00445 op_attr_success = 1; 00446 file_type = htonl(NF4DIR); /* There are only directories in the pseudo fs */ 00447 00448 memcpy((char *)(attrvalsBuffer + LastOffset), &file_type, sizeof(fattr4_type)); 00449 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00450 break; 00451 00452 case FATTR4_FH_EXPIRE_TYPE: 00453 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00454 "-----> Wanting FATTR4_FH_EXPIRE_TYPE"); 00455 00456 /* For the moment, we handle only the persistent filehandle 00457 expire_type = htonl(FH4_VOLATILE_ANY); */ 00458 expire_type = htonl( FH4_PERSISTENT ) ; 00459 memcpy((char *)(attrvalsBuffer + LastOffset), &expire_type, 00460 sizeof(expire_type)); 00461 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00462 op_attr_success = 1; 00463 break; 00464 00465 case FATTR4_CHANGE: 00466 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00467 "-----> Wanting FATTR4_CHANGE"); 00468 00469 /* Use boot time as time value for every pseudo fs object */ 00470 memset(&file_change, 0, sizeof(changeid4)); 00471 file_change = nfs_htonl64((changeid4) ServerBootTime); 00472 00473 memcpy((char *)(attrvalsBuffer + LastOffset), &file_change, 00474 sizeof(fattr4_change)); 00475 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00476 op_attr_success = 1; 00477 break; 00478 00479 case FATTR4_SIZE: 00480 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00481 "-----> Wanting FATTR4_SIZE"); 00482 00483 file_size = nfs_htonl64((fattr4_size) DEV_BSIZE); 00484 memcpy((char *)(attrvalsBuffer + LastOffset), &file_size, sizeof(fattr4_size)); 00485 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00486 op_attr_success = 1; 00487 break; 00488 00489 case FATTR4_LINK_SUPPORT: 00490 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00491 "-----> Wanting FATTR4_LINK_SUPPORT"); 00492 00493 /* HPSS NameSpace support hard link */ 00494 link_support = htonl(TRUE); 00495 memcpy((char *)(attrvalsBuffer + LastOffset), &link_support, 00496 sizeof(fattr4_link_support)); 00497 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00498 op_attr_success = 1; 00499 break; 00500 00501 case FATTR4_SYMLINK_SUPPORT: 00502 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00503 "-----> Wanting FATTR4_SYMLINK_SUPPORT"); 00504 00505 /* HPSS NameSpace support symbolic link */ 00506 symlink_support = htonl(TRUE); 00507 memcpy((char *)(attrvalsBuffer + LastOffset), &symlink_support, 00508 sizeof(fattr4_symlink_support)); 00509 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00510 op_attr_success = 1; 00511 break; 00512 00513 case FATTR4_NAMED_ATTR: 00514 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00515 "-----> Wanting FATTR4_NAMED_ATTR"); 00516 00517 /* For this version of the binary, named attributes is not supported */ 00518 named_attr = htonl(FALSE); 00519 memcpy((char *)(attrvalsBuffer + LastOffset), &named_attr, 00520 sizeof(fattr4_named_attr)); 00521 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00522 op_attr_success = 1; 00523 break; 00524 00525 case FATTR4_FSID: 00526 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00527 "-----> Wanting FATTR4_FSID"); 00528 00529 /* The file system id (should be unique per fileset according to the HPSS logic) */ 00530 if(psfsp->junction_export == NULL) 00531 { 00532 fsid.major = nfs_htonl64(152LL); 00533 fsid.minor = nfs_htonl64(152LL); 00534 } 00535 else 00536 { 00537 fsid.major = nfs_htonl64(153LL); /* @todo BUGAZOMEU : tres cradem mais utile */ 00538 fsid.minor = nfs_htonl64(153LL); 00539 } 00540 memcpy((char *)(attrvalsBuffer + LastOffset), &fsid, sizeof(fattr4_fsid)); 00541 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00542 op_attr_success = 1; 00543 break; 00544 00545 case FATTR4_UNIQUE_HANDLES: 00546 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00547 "-----> Wanting FATTR4_UNIQUE_HANDLES"); 00548 00549 /* Filehandles are unique */ 00550 unique_handles = htonl(TRUE); 00551 memcpy((char *)(attrvalsBuffer + LastOffset), &unique_handles, 00552 sizeof(fattr4_unique_handles)); 00553 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00554 op_attr_success = 1; 00555 break; 00556 00557 case FATTR4_LEASE_TIME: 00558 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00559 "-----> Wanting FATTR4_LEASE_TIME"); 00560 00561 lease_time = htonl(nfs_param.nfsv4_param.lease_lifetime); 00562 memcpy((char *)(attrvalsBuffer + LastOffset), &lease_time, 00563 sizeof(fattr4_lease_time)); 00564 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00565 op_attr_success = 1; 00566 break; 00567 00568 case FATTR4_RDATTR_ERROR: 00569 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00570 "-----> Wanting FATTR4_RDATTR_ERROR"); 00571 00572 op_attr_success = htonl(0); /* not used in a getattr call */ 00573 break; 00574 00575 case FATTR4_ACL: 00576 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00577 "-----> Wanting FATTR4_ACL"); 00578 00579 acl.fattr4_acl_len = htonl(0); 00580 memcpy((char *)(attrvalsBuffer + LastOffset), &acl, sizeof(fattr4_acl)); 00581 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00582 op_attr_success = 1; 00583 break; 00584 00585 case FATTR4_ACLSUPPORT: 00586 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00587 "-----> Wanting FATTR4_ACL_SUPPORT"); 00588 00589 #ifdef _USE_NFS4_ACL 00590 aclsupport = htonl(ACL4_SUPPORT_ALLOW_ACL | ACL4_SUPPORT_DENY_ACL); 00591 #else 00592 aclsupport = htonl(0); 00593 #endif 00594 memcpy((char *)(attrvalsBuffer + LastOffset), &aclsupport, 00595 sizeof(fattr4_aclsupport)); 00596 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00597 op_attr_success = 1; 00598 break; 00599 00600 case FATTR4_ARCHIVE: 00601 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00602 "-----> Wanting FATTR4_ARCHIVE"); 00603 00604 /* Archive flag is not supported */ 00605 archive = htonl(FALSE); 00606 memcpy((char *)(attrvalsBuffer + LastOffset), &archive, sizeof(fattr4_archive)); 00607 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00608 op_attr_success = 1; 00609 break; 00610 00611 case FATTR4_CANSETTIME: 00612 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00613 "-----> Wanting FATTR4_CANSETTIME"); 00614 00615 /* The time can be set on files */ 00616 cansettime = htonl(TRUE); 00617 memcpy((char *)(attrvalsBuffer + LastOffset), &cansettime, 00618 sizeof(fattr4_cansettime)); 00619 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00620 op_attr_success = 1; 00621 break; 00622 00623 case FATTR4_CASE_INSENSITIVE: 00624 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00625 "-----> Wanting FATTR4_CASE_INSENSITIVE"); 00626 00627 /* pseudofs is not case INSENSITIVE... it is Read-Only */ 00628 case_insensitive = htonl(FALSE); 00629 memcpy((char *)(attrvalsBuffer + LastOffset), &case_insensitive, 00630 sizeof(fattr4_case_insensitive)); 00631 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00632 op_attr_success = 1; 00633 break; 00634 00635 case FATTR4_CASE_PRESERVING: 00636 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00637 "-----> Wanting FATTR4_PRESERVING"); 00638 00639 /* pseudofs is case preserving... it is Read-Only */ 00640 case_preserving = htonl(TRUE); 00641 memcpy((char *)(attrvalsBuffer + LastOffset), &case_preserving, 00642 sizeof(fattr4_case_preserving)); 00643 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00644 op_attr_success = 1; 00645 break; 00646 00647 case FATTR4_CHOWN_RESTRICTED: 00648 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00649 "-----> Wanting FATTR4_CHOWN_RESTRICTED"); 00650 00651 /* chown is restricted to root, but in fact no chown will be done on pseudofs */ 00652 chown_restricted = htonl(TRUE); 00653 memcpy((char *)(attrvalsBuffer + LastOffset), &chown_restricted, 00654 sizeof(fattr4_chown_restricted)); 00655 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00656 op_attr_success = 1; 00657 break; 00658 00659 case FATTR4_FILEHANDLE: 00660 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00661 "-----> Wanting FATTR4_FILEHANDLE"); 00662 00663 /* Return the file handle */ 00664 fhandle_len = htonl(objFH->nfs_fh4_len); 00665 00666 memcpy((char *)(attrvalsBuffer + LastOffset), &fhandle_len, sizeof(u_int)); 00667 LastOffset += sizeof(u_int); 00668 00669 memcpy((char *)(attrvalsBuffer + LastOffset), 00670 objFH->nfs_fh4_val, objFH->nfs_fh4_len); 00671 LastOffset += objFH->nfs_fh4_len; 00672 00673 /* XDR's special stuff for 32-bit alignment */ 00674 len = objFH->nfs_fh4_len; 00675 off = 0; 00676 while((len + off) % 4 != 0) 00677 { 00678 char c = '\0'; 00679 00680 off += 1; 00681 memset((char *)(attrvalsBuffer + LastOffset), c, 1); 00682 LastOffset += 1; 00683 } 00684 00685 op_attr_success = 1; 00686 break; 00687 00688 case FATTR4_FILEID: 00689 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00690 "-----> Wanting FATTR4_FILEID"); 00691 00692 /* The analog to the inode number. RFC3530 says "a number uniquely identifying the file within the filesystem" 00693 * In the case of a pseudofs entry, the entry's unique id is used */ 00694 file_id = nfs_htonl64((fattr4_fileid) psfsp->pseudo_id); 00695 00696 memcpy((char *)(attrvalsBuffer + LastOffset), &file_id, sizeof(fattr4_fileid)); 00697 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00698 op_attr_success = 1; 00699 break; 00700 00701 case FATTR4_FILES_AVAIL: 00702 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00703 "-----> Wanting FATTR4_FILES_AVAIL"); 00704 00705 files_avail = nfs_htonl64((fattr4_files_avail) 512); /* Fake value */ 00706 memcpy((char *)(attrvalsBuffer + LastOffset), &files_avail, 00707 sizeof(fattr4_files_avail)); 00708 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00709 op_attr_success = 1; 00710 break; 00711 00712 case FATTR4_FILES_FREE: 00713 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00714 "-----> Wanting FATTR4_FILES_FREE"); 00715 00716 files_free = nfs_htonl64((fattr4_files_avail) 512); /* Fake value */ 00717 memcpy((char *)(attrvalsBuffer + LastOffset), &files_free, 00718 sizeof(fattr4_files_free)); 00719 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00720 op_attr_success = 1; 00721 break; 00722 00723 case FATTR4_FILES_TOTAL: 00724 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00725 "-----> Wanting FATTR4_FILES_TOTAL"); 00726 00727 files_total = nfs_htonl64((fattr4_files_avail) 512); /* Fake value */ 00728 memcpy((char *)(attrvalsBuffer + LastOffset), &files_total, 00729 sizeof(fattr4_files_total)); 00730 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00731 op_attr_success = 1; 00732 break; 00733 00734 case FATTR4_FS_LOCATIONS: 00735 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00736 "-----> Wanting FATTR4_FS_LOCATIONS"); 00737 /* RFC 3530: "When the fs_locations attribute is interrogated and there are no 00738 alternate file system locations, the server SHOULD return a zero- 00739 length array of fs_location4 structures, together with a valid 00740 fs_root. The code below does not return a fs_root which causes client 00741 problems when they interrogate this attribute. For now moving attribute to 00742 unsupported. 00743 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00744 op_attr_success = 1; 00745 */ 00746 op_attr_success = 0; 00747 break; 00748 00749 case FATTR4_HIDDEN: 00750 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00751 "-----> Wanting FATTR4_HIDDEN"); 00752 00753 /* There are no hidden file in pseudofs */ 00754 hidden = htonl(FALSE); 00755 memcpy((char *)(attrvalsBuffer + LastOffset), &hidden, sizeof(fattr4_hidden)); 00756 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00757 op_attr_success = 1; 00758 break; 00759 00760 case FATTR4_HOMOGENEOUS: 00761 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00762 "-----> Wanting FATTR4_HOMOGENEOUS"); 00763 00764 /* Unix semantic is homogeneous (all objects have the same kind of attributes) */ 00765 homogeneous = htonl(TRUE); 00766 memcpy((char *)(attrvalsBuffer + LastOffset), &homogeneous, 00767 sizeof(fattr4_homogeneous)); 00768 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00769 op_attr_success = 1; 00770 break; 00771 00772 case FATTR4_MAXFILESIZE: 00773 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00774 "-----> Wanting FATTR4_MAXFILESIZE"); 00775 00776 max_filesize = nfs_htonl64((fattr4_maxfilesize) FSINFO_MAX_FILESIZE); 00777 memcpy((char *)(attrvalsBuffer + LastOffset), &max_filesize, 00778 sizeof(fattr4_maxfilesize)); 00779 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00780 op_attr_success = 1; 00781 break; 00782 00783 case FATTR4_MAXLINK: 00784 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00785 "-----> Wanting FATTR4_MAXLINK"); 00786 00787 maxlink = htonl(MAX_HARD_LINK_VALUE); 00788 memcpy((char *)(attrvalsBuffer + LastOffset), &maxlink, sizeof(fattr4_maxlink)); 00789 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00790 op_attr_success = 1; 00791 break; 00792 00793 case FATTR4_MAXNAME: 00794 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00795 "-----> Wanting FATTR4_MAXNAME"); 00796 00797 maxname = htonl((fattr4_maxname) MAXNAMLEN); 00798 memcpy((char *)(attrvalsBuffer + LastOffset), &maxname, sizeof(fattr4_maxname)); 00799 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00800 op_attr_success = 1; 00801 break; 00802 00803 case FATTR4_MAXREAD: 00804 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00805 "-----> Wanting FATTR4_MAXREAD"); 00806 00807 maxread = nfs_htonl64((fattr4_maxread) NFS4_PSEUDOFS_MAX_READ_SIZE); 00808 memcpy((char *)(attrvalsBuffer + LastOffset), &maxread, sizeof(fattr4_maxread)); 00809 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00810 op_attr_success = 1; 00811 break; 00812 00813 case FATTR4_MAXWRITE: 00814 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00815 "-----> Wanting FATTR4_MAXWRITE"); 00816 00817 maxwrite = nfs_htonl64((fattr4_maxwrite) NFS4_PSEUDOFS_MAX_WRITE_SIZE); 00818 memcpy((char *)(attrvalsBuffer + LastOffset), &maxwrite, 00819 sizeof(fattr4_maxwrite)); 00820 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00821 op_attr_success = 1; 00822 break; 00823 00824 case FATTR4_MIMETYPE: 00825 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00826 "-----> Wanting FATTR4_MIMETYPE"); 00827 00828 mimetype.utf8string_len = htonl(0); 00829 memcpy((char *)(attrvalsBuffer + LastOffset), &mimetype, 00830 sizeof(fattr4_mimetype)); 00831 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00832 op_attr_success = 1; /* No supported for the moment */ 00833 break; 00834 00835 case FATTR4_MODE: 00836 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00837 "-----> Wanting FATTR4_MODE"); 00838 00839 file_mode = htonl(0555); /* Every pseudo fs object is dr-xr-xr-x */ 00840 memcpy((char *)(attrvalsBuffer + LastOffset), &file_mode, sizeof(fattr4_mode)); 00841 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00842 op_attr_success = 1; 00843 break; 00844 00845 case FATTR4_NO_TRUNC: 00846 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00847 "-----> Wanting FATTR4_NO_TRUNC"); 00848 00849 /* File's names are not truncated, an error is returned is name is too long */ 00850 no_trunc = htonl(TRUE); 00851 memcpy((char *)(attrvalsBuffer + LastOffset), &no_trunc, 00852 sizeof(fattr4_no_trunc)); 00853 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00854 op_attr_success = 1; 00855 break; 00856 00857 case FATTR4_NUMLINKS: 00858 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00859 "-----> Wanting FATTR4_NUMLINKS"); 00860 00861 /* Reply the number of links found in vattr structure */ 00862 file_numlinks = htonl((fattr4_numlinks) 1); 00863 memcpy((char *)(attrvalsBuffer + LastOffset), &file_numlinks, 00864 sizeof(fattr4_numlinks)); 00865 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00866 op_attr_success = 1; 00867 break; 00868 00869 case FATTR4_OWNER: 00870 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00871 "-----> Wanting FATTR4_OWNER"); 00872 00873 /* Return the uid as a human readable utf8 string */ 00874 if(uid2utf8(NFS4_ROOT_UID, &file_owner) == 0) 00875 { 00876 u_int utf8len = 0; 00877 u_int deltalen = 0; 00878 00879 /* Take care of 32 bits alignment */ 00880 if(file_owner.utf8string_len % 4 == 0) 00881 deltalen = 0; 00882 else 00883 deltalen = 4 - file_owner.utf8string_len % 4; 00884 /* Following code used to add deltalen to utf8len which is wrong. It caused 00885 * clients verifying utf8 strings to reject the attribute. 00886 */ 00887 utf8len = htonl(file_owner.utf8string_len); 00888 memcpy((char *)(attrvalsBuffer + LastOffset), &utf8len, sizeof(u_int)); 00889 LastOffset += sizeof(u_int); 00890 00891 memcpy((char *)(attrvalsBuffer + LastOffset), 00892 file_owner.utf8string_val, file_owner.utf8string_len); 00893 LastOffset += file_owner.utf8string_len; 00894 00895 /* Free what was allocated by uid2utf8 */ 00896 gsh_free(file_owner.utf8string_val); 00897 00898 /* Pad with zero to keep xdr alignement */ 00899 if(deltalen != 0) 00900 memset((char *)(attrvalsBuffer + LastOffset), 0, deltalen); 00901 LastOffset += deltalen; 00902 00903 op_attr_success = 1; 00904 } 00905 else 00906 op_attr_success = 0; 00907 break; 00908 00909 case FATTR4_OWNER_GROUP: 00910 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00911 "-----> Wanting FATTR4_OWNER_GROUP"); 00912 00913 /* Return the uid as a human readable utf8 string */ 00914 if(gid2utf8(2, &file_owner_group) == 0) 00915 { 00916 u_int utf8len = 0; 00917 u_int deltalen = 0; 00918 00919 /* Take care of 32 bits alignment */ 00920 if(file_owner_group.utf8string_len % 4 == 0) 00921 deltalen = 0; 00922 else 00923 deltalen = 4 - file_owner_group.utf8string_len % 4; 00924 00925 /* Following code used to add deltalen to utf8len which is wrong. It caused 00926 * clients verifying utf8 strings to reject the attribute. 00927 */ 00928 utf8len = htonl(file_owner_group.utf8string_len); 00929 memcpy((char *)(attrvalsBuffer + LastOffset), &utf8len, sizeof(u_int)); 00930 LastOffset += sizeof(u_int); 00931 00932 memcpy((char *)(attrvalsBuffer + LastOffset), 00933 file_owner_group.utf8string_val, file_owner_group.utf8string_len); 00934 LastOffset += file_owner_group.utf8string_len; 00935 00936 /* Free what was used for utf8 conversion */ 00937 gsh_free(file_owner_group.utf8string_val); 00938 00939 /* Pad with zero to keep xdr alignement */ 00940 if(deltalen != 0) 00941 memset((char *)(attrvalsBuffer + LastOffset), 0, deltalen); 00942 LastOffset += deltalen; 00943 00944 op_attr_success = 1; 00945 } 00946 else 00947 op_attr_success = 0; 00948 break; 00949 00950 case FATTR4_QUOTA_AVAIL_HARD: 00951 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00952 "-----> Wanting FATTR4_QUOTA_AVAIL_HARD"); 00953 00954 quota_avail_hard = nfs_htonl64((fattr4_quota_avail_hard) NFS_V4_MAX_QUOTA_HARD); 00955 memcpy((char *)(attrvalsBuffer + LastOffset), "a_avail_hard, 00956 sizeof(fattr4_quota_avail_hard)); 00957 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00958 op_attr_success = 1; 00959 break; 00960 00961 case FATTR4_QUOTA_AVAIL_SOFT: 00962 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00963 "-----> Wanting FATTR4_QUOTA_AVAIL_SOFT"); 00964 00965 quota_avail_soft = nfs_htonl64((fattr4_quota_avail_soft) NFS_V4_MAX_QUOTA_SOFT); 00966 memcpy((char *)(attrvalsBuffer + LastOffset), "a_avail_soft, 00967 sizeof(fattr4_quota_avail_soft)); 00968 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00969 op_attr_success = 1; 00970 break; 00971 00972 case FATTR4_QUOTA_USED: 00973 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00974 "-----> Wanting FATTR4_QUOTA_AVAIL_USED"); 00975 00976 quota_used = nfs_htonl64((fattr4_quota_used) NFS_V4_MAX_QUOTA); 00977 memcpy((char *)(attrvalsBuffer + LastOffset), "a_used, 00978 sizeof(fattr4_quota_used)); 00979 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00980 op_attr_success = 1; 00981 break; 00982 00983 case FATTR4_RAWDEV: 00984 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00985 "-----> Wanting FATTR4_RAWDEV"); 00986 00987 /* Not usefull, there are no special block or character file in HPSS */ 00988 /* since FATTR4_TYPE will never be NFS4BLK or NFS4CHR, this value should not be used by the client */ 00989 rawdev.specdata1 = htonl(0); 00990 rawdev.specdata2 = htonl(0); 00991 memcpy((char *)(attrvalsBuffer + LastOffset), &rawdev, sizeof(fattr4_rawdev)); 00992 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 00993 op_attr_success = 1; 00994 break; 00995 00996 case FATTR4_SPACE_AVAIL: 00997 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 00998 "-----> Wanting FATTR4_SPACE_AVAIL"); 00999 01000 space_avail = nfs_htonl64(512000LL); /* Fake value */ 01001 memcpy((char *)(attrvalsBuffer + LastOffset), &space_avail, 01002 sizeof(fattr4_space_avail)); 01003 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01004 op_attr_success = 1; 01005 break; 01006 01007 case FATTR4_SPACE_FREE: 01008 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01009 "-----> Wanting FATTR4_SPACE_FREE"); 01010 01011 space_free = nfs_htonl64(512000LL); /* Fake value */ 01012 memcpy((char *)(attrvalsBuffer + LastOffset), &space_free, 01013 sizeof(fattr4_space_free)); 01014 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01015 op_attr_success = 1; 01016 break; 01017 01018 case FATTR4_SPACE_TOTAL: 01019 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01020 "-----> Wanting FATTR4_SPACE_TOTAL"); 01021 01022 space_total = nfs_htonl64(1024000LL); /* Fake value */ 01023 memcpy((char *)(attrvalsBuffer + LastOffset), &space_total, 01024 sizeof(fattr4_space_total)); 01025 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01026 op_attr_success = 1; 01027 break; 01028 01029 case FATTR4_SPACE_USED: 01030 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01031 "-----> Wanting FATTR4_SPACE_USED"); 01032 01033 /* the number of bytes on the filesystem used by the object, which is slightly different 01034 * from the file's size (there can be hole in the file) */ 01035 file_space_used = nfs_htonl64((fattr4_space_used) DEV_BSIZE); 01036 memcpy((char *)(attrvalsBuffer + LastOffset), &file_space_used, 01037 sizeof(fattr4_space_used)); 01038 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01039 op_attr_success = 1; 01040 break; 01041 01042 case FATTR4_SYSTEM: 01043 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01044 "-----> Wanting FATTR4_SYSTEM"); 01045 01046 /* This is not a windows system File-System with respect to the regarding API */ 01047 system = htonl(FALSE); 01048 memcpy((char *)(attrvalsBuffer + LastOffset), &system, sizeof(fattr4_system)); 01049 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01050 op_attr_success = 1; 01051 break; 01052 01053 case FATTR4_TIME_ACCESS: 01054 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01055 "-----> Wanting FATTR4_TIME_ACCESS"); 01056 01057 /* This will contain the object's time os last access, the 'atime' in the Unix semantic */ 01058 memset(&(time_access.seconds), 0, sizeof(int64_t)); 01059 time_access.seconds = nfs_htonl64((int64_t) ServerBootTime); 01060 time_access.nseconds = htonl(0); 01061 memcpy((char *)(attrvalsBuffer + LastOffset), &time_access, 01062 fattr4tab[attribute_to_set].size_fattr4); 01063 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01064 op_attr_success = 1; 01065 break; 01066 01067 case FATTR4_TIME_ACCESS_SET: 01068 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01069 "-----> Wanting FATTR4_TIME_ACCESS_SET"); 01070 01071 /* To be used with NFS4_OP_SETATTR only */ 01072 op_attr_success = 0; 01073 break; 01074 01075 case FATTR4_TIME_BACKUP: 01076 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01077 "-----> Wanting FATTR4_TIME_BACKUP"); 01078 01079 /* No time backup, return unix's beginning of time */ 01080 time_backup.seconds = nfs_htonl64(0LL); 01081 time_backup.nseconds = htonl(0); 01082 memcpy((char *)(attrvalsBuffer + LastOffset), &time_backup, 01083 fattr4tab[attribute_to_set].size_fattr4); 01084 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01085 op_attr_success = 1; 01086 break; 01087 01088 case FATTR4_TIME_CREATE: 01089 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01090 "-----> Wanting FATTR4_TIME_CREATE"); 01091 01092 /* No time create, return unix's beginning of time */ 01093 time_create.seconds = nfs_htonl64(0LL); 01094 time_create.nseconds = htonl(0); 01095 memcpy((char *)(attrvalsBuffer + LastOffset), &time_create, 01096 fattr4tab[attribute_to_set].size_fattr4); 01097 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01098 op_attr_success = 1; 01099 break; 01100 01101 case FATTR4_TIME_DELTA: 01102 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01103 "-----> Wanting FATTR4_TIME_DELTA"); 01104 01105 01106 /* According to RFC3530, this is "the smallest usefull server time granularity", I set this to 1s */ 01107 time_delta.seconds = nfs_htonl64(1LL); 01108 time_delta.nseconds = 0; 01109 memcpy((char *)(attrvalsBuffer + LastOffset), &time_delta, 01110 fattr4tab[attribute_to_set].size_fattr4); 01111 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01112 op_attr_success = 1; 01113 break; 01114 01115 case FATTR4_TIME_METADATA: 01116 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01117 "-----> Wanting FATTR4_TIME_METADATA"); 01118 01119 /* The time for the last metadata operation, the ctime in the unix's semantic */ 01120 memset(&(time_metadata.seconds), 0, sizeof(int64_t)); 01121 time_metadata.seconds = nfs_htonl64((int64_t) ServerBootTime); 01122 time_metadata.nseconds = htonl(0); 01123 memcpy((char *)(attrvalsBuffer + LastOffset), &time_metadata, 01124 fattr4tab[attribute_to_set].size_fattr4); 01125 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01126 op_attr_success = 1; 01127 break; 01128 01129 case FATTR4_TIME_MODIFY: 01130 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01131 "-----> Wanting FATTR4_TIME_MODIFY"); 01132 01133 /* The time for the last modify operation, the mtime in the unix's semantic */ 01134 memset(&(time_modify.seconds), 0, sizeof(int64_t)); 01135 time_modify.seconds = nfs_htonl64((int64_t) ServerBootTime); 01136 time_modify.nseconds = htonl(0); 01137 memcpy((char *)(attrvalsBuffer + LastOffset), &time_modify, 01138 fattr4tab[attribute_to_set].size_fattr4); 01139 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01140 op_attr_success = 1; 01141 break; 01142 01143 case FATTR4_TIME_MODIFY_SET: 01144 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01145 "-----> Wanting FATTR4_TIME_MODIFY_SET"); 01146 01147 op_attr_success = 0; /* should never be used here, only for setattr */ 01148 break; 01149 01150 case FATTR4_MOUNTED_ON_FILEID: 01151 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01152 "-----> Wanting FATTR4_MOUNTED_ON_FILEID"); 01153 01154 mounted_on_fileid = nfs_htonl64((fattr4_fileid) psfsp->pseudo_id); 01155 memcpy((char *)(attrvalsBuffer + LastOffset), &mounted_on_fileid, 01156 sizeof(fattr4_mounted_on_fileid)); 01157 LastOffset += fattr4tab[attribute_to_set].size_fattr4; 01158 op_attr_success = 1; 01159 break; 01160 01161 #ifdef _USE_NFS4_1 01162 case FATTR4_FS_LAYOUT_TYPES: 01163 layout_types.fattr4_fs_layout_types_len = htonl(1); 01164 memcpy((char *)(attrvalsBuffer + LastOffset), 01165 &layout_types.fattr4_fs_layout_types_len, sizeof(u_int)); 01166 LastOffset += sizeof(u_int); 01167 01168 layout_types.fattr4_fs_layout_types_val = layouts; 01169 layouts[0] = htonl(LAYOUT4_NFSV4_1_FILES); 01170 memcpy((char *)(attrvalsBuffer + LastOffset), 01171 layout_types.fattr4_fs_layout_types_val, sizeof(layouttype4)); 01172 LastOffset += sizeof(layouttype4); 01173 01174 op_attr_success = 1; 01175 break; 01176 #endif 01177 01178 default: 01179 LogWarn(COMPONENT_NFS_V4_PSEUDO, "Bad file attributes %d queried", 01180 attribute_to_set); 01181 /* BUGAZOMEU : un traitement special ici */ 01182 break; 01183 } /* switch( attr_to_set ) */ 01184 01185 /* Increase the Offset for the next operation if this was a success */ 01186 if(op_attr_success) 01187 { 01188 /* Set the returned bitmask */ 01189 attrvalslist[j] = attribute_to_set; 01190 j += 1; 01191 01192 /* Be carefull not to get out of attrvalsBuffer */ 01193 if(LastOffset > NFS4_ATTRVALS_BUFFLEN) 01194 return -1; 01195 } 01196 01197 } /* for i */ 01198 01199 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01200 "----------------------------------------"); 01201 01202 /* LastOffset contains the length of the attrvalsBuffer usefull data */ 01203 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01204 "Fattr (pseudo) At the end LastOffset = %u, i=%d, j=%d", 01205 LastOffset, i, j); 01206 01207 return nfs4_Fattr_Fill(Fattr, j, attrvalslist, LastOffset, attrvalsBuffer); 01208 } /* nfs4_PseudoToFattr */ 01209 01221 int nfs4_FhandleToPseudo(nfs_fh4 * fh4p, pseudofs_t * psfstree, 01222 pseudofs_entry_t * psfsentry) 01223 { 01224 file_handle_v4_t *pfhandle4; 01225 01226 /* Map the filehandle to the correct structure */ 01227 pfhandle4 = (file_handle_v4_t *) (fh4p->nfs_fh4_val); 01228 01229 /* The function must be called with a fh pointed to a pseudofs entry */ 01230 if(pfhandle4->pseudofs_flag == FALSE) 01231 return FALSE; 01232 01233 /* Get the object pointer by using the reverse tab in the pseudofs structure */ 01234 memcpy(psfsentry, psfstree->reverse_tab[pfhandle4->pseudofs_id], 01235 sizeof(pseudofs_entry_t)); 01236 01237 return TRUE; 01238 } /* nfs4_FhandleToPseudo */ 01239 01252 int nfs4_PseudoToFhandle(nfs_fh4 * fh4p, pseudofs_entry_t * psfsentry) 01253 { 01254 file_handle_v4_t *fhandle4; 01255 01256 memset(fh4p->nfs_fh4_val, 0, sizeof(struct alloc_file_handle_v4)); /* clean whole thing */ 01257 fhandle4 = (file_handle_v4_t *)fh4p->nfs_fh4_val; 01258 fhandle4->fhversion = GANESHA_FH_VERSION; 01259 fhandle4->pseudofs_flag = TRUE; 01260 fhandle4->pseudofs_id = psfsentry->pseudo_id; 01261 01262 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, "PSEUDO_TO_FH: Pseudo id = %d -> %d", 01263 psfsentry->pseudo_id, fhandle4->pseudofs_id); 01264 01265 fh4p->nfs_fh4_len = sizeof(file_handle_v4_t); /* no handle in opaque */ 01266 01267 return TRUE; 01268 } /* nfs4_PseudoToFhandle */ 01269 01282 int nfs4_CreateROOTFH4(nfs_fh4 * fh4p, compound_data_t * data) 01283 { 01284 pseudofs_entry_t psfsentry; 01285 int status = 0; 01286 01287 psfsentry = *(data->pseudofs->reverse_tab[0]); 01288 01289 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01290 "CREATE ROOTFH (pseudo): root to pseudofs = #%s#", 01291 psfsentry.name); 01292 01293 if((status = nfs4_AllocateFH(&(data->rootFH))) != NFS4_OK) 01294 return status; 01295 01296 if(!nfs4_PseudoToFhandle(&(data->rootFH), &psfsentry)) 01297 { 01298 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01299 "CREATE ROOTFH (pseudo): Creation of root fh is impossible"); 01300 return NFS4ERR_BADHANDLE; 01301 } 01302 01303 /* Test */ 01304 if(isFullDebug(COMPONENT_NFS_V4)) 01305 { 01306 char str[LEN_FH_STR]; 01307 sprint_fhandle4(str, &data->rootFH); 01308 LogFullDebug(COMPONENT_NFS_V4, "CREATE ROOT FH: %s", str); 01309 } 01310 01311 return NFS4_OK; 01312 } /* nfs4_CreateROOTFH4 */ 01313 01327 #define arg_GETATTR4 op->nfs_argop4_u.opgetattr 01328 #define res_GETATTR4 resp->nfs_resop4_u.opgetattr 01329 01330 int nfs4_op_getattr_pseudo(struct nfs_argop4 *op, 01331 compound_data_t * data, struct nfs_resop4 *resp) 01332 { 01333 pseudofs_entry_t psfsentry; 01334 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_getattr"; 01335 01336 resp->resop = NFS4_OP_GETATTR; 01337 01338 /* Get the pseudo entry related to this fhandle */ 01339 if(!nfs4_FhandleToPseudo(&(data->currentFH), data->pseudofs, &psfsentry)) 01340 { 01341 res_GETATTR4.status = NFS4ERR_BADHANDLE; 01342 return res_GETATTR4.status; 01343 } 01344 01345 /* All directories in pseudo fs have the same Fattr */ 01346 if(nfs4_PseudoToFattr(&psfsentry, 01347 &(res_GETATTR4.GETATTR4res_u.resok4.obj_attributes), 01348 data, &(data->currentFH), &(arg_GETATTR4.attr_request)) != 0) 01349 res_GETATTR4.status = NFS4ERR_SERVERFAULT; 01350 else 01351 res_GETATTR4.status = NFS4_OK; 01352 01353 LogFullDebug(COMPONENT_NFS_V4, 01354 "Apres nfs4_PseudoToFattr: attrmask(bitmap4_len)=%d attrlist4_len=%d", 01355 res_GETATTR4.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len, 01356 res_GETATTR4.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len); 01357 01358 return res_GETATTR4.status; 01359 } /* nfs4_op_getattr */ 01360 01375 /* Shorter notation to avoid typos */ 01376 #define res_ACCESS4 resp->nfs_resop4_u.opaccess 01377 #define arg_ACCESS4 op->nfs_argop4_u.opaccess 01378 01379 int nfs4_op_access_pseudo(struct nfs_argop4 *op, 01380 compound_data_t * data, struct nfs_resop4 *resp) 01381 { 01382 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_access_pseudo"; 01383 01384 resp->resop = NFS4_OP_ACCESS; 01385 01386 /* All access types are supported */ 01387 res_ACCESS4.ACCESS4res_u.resok4.supported = ACCESS4_READ | ACCESS4_LOOKUP; 01388 01389 /* DELETE/MODIFY/EXTEND are not supported in the pseudo fs */ 01390 res_ACCESS4.ACCESS4res_u.resok4.access = 01391 arg_ACCESS4.access & ~(ACCESS4_MODIFY | ACCESS4_EXTEND | ACCESS4_DELETE); 01392 01393 return NFS4_OK; 01394 } /* nfs4_op_access_pseudo */ 01395 01409 /* Shorter notation to avoid typos */ 01410 #define arg_LOOKUP4 op->nfs_argop4_u.oplookup 01411 #define res_LOOKUP4 resp->nfs_resop4_u.oplookup 01412 01413 int nfs4_op_lookup_pseudo(struct nfs_argop4 *op, 01414 compound_data_t * data, struct nfs_resop4 *resp) 01415 { 01416 char name[MAXNAMLEN]; 01417 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookup_pseudo"; 01418 pseudofs_entry_t psfsentry; 01419 pseudofs_entry_t *iter = NULL; 01420 int found = FALSE; 01421 int pseudo_is_slash = FALSE ; 01422 int error = 0; 01423 cache_inode_status_t cache_status = 0; 01424 fsal_status_t fsal_status; 01425 cache_inode_fsal_data_t fsdata; 01426 fsal_path_t exportpath_fsal; 01427 char pathfsal[MAXPATHLEN] ; 01428 fsal_attrib_list_t attr; 01429 fsal_handle_t fsal_handle; 01430 cache_entry_t *pentry = NULL; 01431 fsal_mdsize_t strsize = MNTPATHLEN + 1; 01432 01433 resp->resop = NFS4_OP_LOOKUP; 01434 01435 /* UTF8 strings may not end with \0, but they carry their length */ 01436 utf82str(name, sizeof(name), &arg_LOOKUP4.objname); 01437 01438 /* Get the pseudo fs entry related to the file handle */ 01439 if(!nfs4_FhandleToPseudo(&(data->currentFH), data->pseudofs, &psfsentry)) 01440 { 01441 res_LOOKUP4.status = NFS4ERR_BADHANDLE; 01442 return res_LOOKUP4.status; 01443 } 01444 01445 01446 /* If "/" is set as pseudopath, then gPseudoFS.root.junction_export is not NULL but 01447 * gPseudoFS.root has no son */ 01448 if( ( gPseudoFs.root.junction_export != NULL ) && ( gPseudoFs.root.sons == NULL ) ) 01449 { 01450 iter = &gPseudoFs.root ; 01451 pseudo_is_slash = TRUE ; 01452 found = TRUE ; 01453 } 01454 else 01455 { 01456 found = FALSE; 01457 for(iter = psfsentry.sons; iter != NULL; iter = iter->next) 01458 { 01459 if(!strcmp(iter->name, name)) 01460 { 01461 found = TRUE; 01462 break; 01463 } 01464 } /* for */ 01465 } /* else */ 01466 01467 if(!found) 01468 { 01469 res_LOOKUP4.status = NFS4ERR_NOENT; 01470 return res_LOOKUP4.status; 01471 } 01472 01473 /* A matching entry was found */ 01474 if(iter->junction_export == NULL) 01475 { 01476 /* The entry is not a junction, we stay within the pseudo fs */ 01477 if(!nfs4_PseudoToFhandle(&(data->currentFH), iter)) 01478 { 01479 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01480 return res_LOOKUP4.status; 01481 } 01482 } 01483 else 01484 { 01485 /* The entry is a junction */ 01486 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01487 "A junction in pseudo fs is traversed: name = %s, id = %d", 01488 iter->name, iter->junction_export->id); 01489 data->pexport = iter->junction_export; 01490 strncpy(data->MntPath, iter->fullname, NFS_MAXPATHLEN); 01491 01492 /* Build credentials */ 01493 if(nfs4_MakeCred(data) != 0) 01494 { 01495 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01496 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get FSAL credentials for %s, id=%d", 01497 data->pexport->fullpath, data->pexport->id); 01498 res_LOOKUP4.status = NFS4ERR_WRONGSEC; 01499 return res_LOOKUP4.status; 01500 } 01501 01502 /* Build fsal data for creation of the first entry */ 01503 strncpy( pathfsal, data->pexport->fullpath, MAXPATHLEN ) ; 01504 01505 if( pseudo_is_slash == TRUE ) 01506 { 01507 strncat( pathfsal, "/", MAXPATHLEN ) ; 01508 strncat( pathfsal, name, MAXPATHLEN - strlen(pathfsal) - 1) ; // - 1 for the '/0' 01509 } 01510 01511 if(FSAL_IS_ERROR 01512 ((fsal_status = 01513 FSAL_str2path( pathfsal, strsize, &exportpath_fsal)))) 01514 { 01515 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01516 return res_LOOKUP4.status; 01517 } 01518 01519 /* Lookup the FSAL to build the fsal handle */ 01520 if(FSAL_IS_ERROR(fsal_status = FSAL_lookupPath(&exportpath_fsal, 01521 data->pcontext, &fsal_handle, NULL))) 01522 { 01523 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01524 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to lookup for %s, id=%d", 01525 data->pexport->fullpath, data->pexport->id); 01526 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01527 "PSEUDO FS JUNCTION TRAVERSAL: fsal_status = ( %d, %d )", 01528 fsal_status.major, fsal_status.minor); 01529 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01530 return res_LOOKUP4.status; 01531 } 01532 01533 if(data->mounted_on_FH.nfs_fh4_len == 0) 01534 { 01535 if((error = nfs4_AllocateFH(&(data->mounted_on_FH))) != NFS4_OK) 01536 { 01537 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01538 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to allocate the 'mounted on' file handle"); 01539 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01540 return res_LOOKUP4.status; 01541 } 01542 } 01543 01544 if(data->currentFH.nfs_fh4_len == 0) 01545 { 01546 if((error = nfs4_AllocateFH(&(data->currentFH))) != NFS4_OK) 01547 { 01548 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01549 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to allocate the first file handle"); 01550 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01551 return res_LOOKUP4.status; 01552 } 01553 } 01554 01555 /* Build the nfs4 handle */ 01556 if(!nfs4_FSALToFhandle(&data->currentFH, &fsal_handle, data)) 01557 { 01558 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01559 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to build the first file handle"); 01560 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01561 return res_LOOKUP4.status; 01562 } 01563 01564 /* The new fh is to be the "mounted on Filehandle" */ 01565 memcpy(data->mounted_on_FH.nfs_fh4_val, data->currentFH.nfs_fh4_val, 01566 sizeof(file_handle_v4_t)); 01567 data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len; 01568 01569 /* Add the entry to the cache as a root (BUGAZOMEU: make it a junction entry when junction is available) */ 01570 fsdata.fh_desc.start = (caddr_t)&fsal_handle; 01571 fsdata.fh_desc.len = 0; 01572 FSAL_ExpandHandle(data->pcontext->export_context, 01573 FSAL_DIGEST_SIZEOF, 01574 &fsdata.fh_desc); 01575 01576 if((pentry = cache_inode_make_root(&fsdata, 01577 data->pcontext, 01578 &cache_status)) == NULL) 01579 { 01580 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01581 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Allocate root entry in cache inode failed, for %s, id=%d", 01582 data->pexport->fullpath, data->pexport->id); 01583 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01584 return res_LOOKUP4.status; 01585 } 01586 01587 /* Get the attributes (costless: the attributes was cached when the root pentry was created */ 01588 if(cache_inode_getattr(pentry, 01589 &attr, 01590 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) 01591 { 01592 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01593 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get attributes for root pentry"); 01594 res_LOOKUP4.status = NFS4ERR_SERVERFAULT; 01595 cache_inode_put(pentry); 01596 return res_LOOKUP4.status; 01597 } 01598 01599 /* Keep the pentry within the compound data */ 01600 if (data->current_entry) { 01601 cache_inode_put(data->current_entry); 01602 } 01603 data->current_entry = pentry; 01604 data->current_filetype = cache_inode_fsal_type_convert(attr.type); 01605 01606 } /* else */ 01607 01608 01609 res_LOOKUP4.status = NFS4_OK; 01610 return NFS4_OK; 01611 } /* nfs4_op_lookup_pseudo */ 01612 01626 /* Shorter notation to avoid typos */ 01627 #define arg_LOOKUPP4 op->nfs_argop4_u.oplookupp 01628 #define res_LOOKUPP4 resp->nfs_resop4_u.oplookupp 01629 01630 int nfs4_op_lookupp_pseudo(struct nfs_argop4 *op, 01631 compound_data_t * data, struct nfs_resop4 *resp) 01632 { 01633 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookup_pseudo"; 01634 pseudofs_entry_t psfsentry; 01635 01636 resp->resop = NFS4_OP_LOOKUPP; 01637 01638 /* Get the pseudo fs entry related to the file handle */ 01639 if(!nfs4_FhandleToPseudo(&(data->currentFH), data->pseudofs, &psfsentry)) 01640 { 01641 res_LOOKUPP4.status = NFS4ERR_BADHANDLE; 01642 return res_LOOKUPP4.status; 01643 } 01644 01645 /* lookupp on the root on the pseudofs should return NFS4ERR_NOENT (RFC3530, page 166) */ 01646 if(!memcmp(&psfsentry, data->pseudofs->reverse_tab[0], sizeof(psfsentry))) 01647 { 01648 res_LOOKUPP4.status = NFS4ERR_NOENT; 01649 return res_LOOKUPP4.status; 01650 } 01651 01652 /* A matching entry was found */ 01653 if(!nfs4_PseudoToFhandle(&(data->currentFH), psfsentry.parent)) 01654 { 01655 res_LOOKUPP4.status = NFS4ERR_SERVERFAULT; 01656 return res_LOOKUPP4.status; 01657 } 01658 01659 /* Copy this to the mounted on FH (if no junction is traversed */ 01660 memcpy((char *)(data->mounted_on_FH.nfs_fh4_val), 01661 (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len); 01662 data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len; 01663 01664 /* Keep the vnode pointer within the data compound */ 01665 if (data->current_entry) { 01666 cache_inode_put(data->current_entry); 01667 } 01668 data->current_entry = NULL; 01669 /* pseudo file system is always a directory and we need to keep 01670 * nfs4_sanity_check_FH happy. 01671 */ 01672 data->current_filetype = DIRECTORY; 01673 res_LOOKUPP4.status = NFS4_OK; 01674 return NFS4_OK; 01675 } /* nfs4_op_lookupp_pseudo */ 01676 01690 /* shorter notation to avoid typo */ 01691 #define arg_READDIR4 op->nfs_argop4_u.opreaddir 01692 #define res_READDIR4 resp->nfs_resop4_u.opreaddir 01693 01694 int nfs4_op_readdir_pseudo(struct nfs_argop4 *op, 01695 compound_data_t * data, struct nfs_resop4 *resp) 01696 { 01697 unsigned long dircount = 0; 01698 unsigned long maxcount = 0; 01699 unsigned long estimated_num_entries = 0; 01700 unsigned long i = 0; 01701 nfs_cookie4 cookie; 01702 verifier4 cookie_verifier; 01703 unsigned long space_used = 0; 01704 pseudofs_entry_t psfsentry; 01705 pseudofs_entry_t *iter = NULL; 01706 entry4 *entry_nfs_array = NULL; 01707 exportlist_t *save_pexport; 01708 nfs_fh4 entryFH; 01709 cache_inode_fsal_data_t fsdata; 01710 fsal_path_t exportpath_fsal; 01711 fsal_attrib_list_t attr; 01712 fsal_handle_t fsal_handle; 01713 fsal_mdsize_t strsize = MNTPATHLEN + 1; 01714 fsal_status_t fsal_status; 01715 int error = 0; 01716 size_t namelen = 0; 01717 cache_inode_status_t cache_status = CACHE_INODE_SUCCESS; 01718 cache_entry_t *pentry = NULL; 01719 01720 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_readdir_pseudo"; 01721 01722 bitmap4 RdAttrErrorBitmap = { 1, (uint32_t *) "\0\0\0\b" }; /* 0xB = 11 = FATTR4_RDATTR_ERROR */ 01723 attrlist4 RdAttrErrorVals = { 0, NULL }; /* Nothing to be seen here */ 01724 01725 resp->resop = NFS4_OP_READDIR; 01726 res_READDIR4.status = NFS4_OK; 01727 01728 entryFH.nfs_fh4_len = 0; 01729 01730 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, "Entering NFS4_OP_READDIR_PSEUDO"); 01731 01732 /* get the caracteristic value for readdir operation */ 01733 dircount = arg_READDIR4.dircount; 01734 maxcount = arg_READDIR4.maxcount; 01735 cookie = arg_READDIR4.cookie; 01736 space_used = sizeof(entry4); 01737 01738 /* dircount is considered meaningless by many nfsv4 client (like the CITI one). we use maxcount instead */ 01739 estimated_num_entries = maxcount / sizeof(entry4); 01740 01741 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01742 "PSEUDOFS READDIR: dircount=%lu, maxcount=%lu, cookie=%"PRIu64", sizeof(entry4)=%lu num_entries=%lu", 01743 dircount, maxcount, (uint64_t)cookie, space_used, estimated_num_entries); 01744 01745 /* If maxcount is too short, return NFS4ERR_TOOSMALL */ 01746 if(maxcount < sizeof(entry4) || estimated_num_entries == 0) 01747 { 01748 res_READDIR4.status = NFS4ERR_TOOSMALL; 01749 return res_READDIR4.status; 01750 } 01751 01752 /* Now resolve the file handle to pseudo fs */ 01753 if(!nfs4_FhandleToPseudo(&(data->currentFH), data->pseudofs, &psfsentry)) 01754 { 01755 res_READDIR4.status = NFS4ERR_BADHANDLE; 01756 return res_READDIR4.status; 01757 } 01758 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01759 "PSEUDOFS READDIR in #%s#", psfsentry.name); 01760 01761 /* If this a junction filehandle ? */ 01762 if(psfsentry.junction_export != NULL) 01763 { 01764 /* This is a junction */ 01765 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01766 "PSEUDOFS READDIR : DIR #%s# id=%u is a junction", 01767 psfsentry.name, psfsentry.junction_export->id); 01768 01769 /* Step up the compound data */ 01770 data->pexport = psfsentry.junction_export; 01771 strncpy(data->MntPath, psfsentry.fullname, NFS_MAXPATHLEN); 01772 01773 /* Build the credentials */ 01774 if(nfs4_MakeCred(data) != 0) 01775 { 01776 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01777 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get FSAL credentials for %s, id=%d", 01778 data->pexport->fullpath, data->pexport->id); 01779 res_READDIR4.status = NFS4ERR_WRONGSEC; 01780 return res_READDIR4.status; 01781 } 01782 /* Build fsal data for creation of the first entry */ 01783 if(FSAL_IS_ERROR 01784 ((fsal_status = 01785 FSAL_str2path(data->pexport->fullpath, strsize, &exportpath_fsal)))) 01786 { 01787 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01788 return res_READDIR4.status; 01789 } 01790 01791 /* Lookup the FSAL to build the fsal handle */ 01792 if(FSAL_IS_ERROR(fsal_status = FSAL_lookupPath(&exportpath_fsal, 01793 data->pcontext, &fsal_handle, NULL))) 01794 { 01795 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01796 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to lookup for %s, id=%d", 01797 data->pexport->fullpath, data->pexport->id); 01798 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01799 "PSEUDO FS JUNCTION TRAVERSAL: fsal_status = ( %d, %d )", 01800 fsal_status.major, fsal_status.minor); 01801 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01802 return res_READDIR4.status; 01803 } 01804 01805 if(data->mounted_on_FH.nfs_fh4_len == 0) 01806 { 01807 if((error = nfs4_AllocateFH(&(data->mounted_on_FH))) != NFS4_OK) 01808 { 01809 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01810 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to allocate the 'mounted on' file handle"); 01811 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01812 return res_READDIR4.status; 01813 } 01814 } 01815 01816 if(data->currentFH.nfs_fh4_len == 0) 01817 { 01818 if((error = nfs4_AllocateFH(&(data->currentFH))) != NFS4_OK) 01819 { 01820 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01821 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to allocate the first file handle"); 01822 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01823 return res_READDIR4.status; 01824 } 01825 } 01826 01827 /* Build the nfs4 handle */ 01828 if(!nfs4_FSALToFhandle(&data->currentFH, &fsal_handle, data)) 01829 { 01830 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01831 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to build the first file handle"); 01832 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01833 return res_READDIR4.status; 01834 } 01835 01836 /* The new fh is to be the "mounted on Filehandle" */ 01837 memcpy(data->mounted_on_FH.nfs_fh4_val, data->currentFH.nfs_fh4_val, 01838 sizeof(file_handle_v4_t)); 01839 data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len; 01840 01841 /* Add the entry to the cache as a root (BUGAZOMEU: make it a junction entry when junction is available) */ 01842 fsdata.fh_desc.start = (caddr_t) &fsal_handle; 01843 fsdata.fh_desc.len = 0; 01844 FSAL_ExpandHandle(data->pcontext->export_context, 01845 FSAL_DIGEST_SIZEOF, 01846 &fsdata.fh_desc); 01847 01848 if((pentry = cache_inode_make_root(&fsdata, 01849 data->pcontext, 01850 &cache_status)) == NULL) 01851 { 01852 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01853 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Allocate root entry in cache inode failed, for %s, id=%d", 01854 data->pexport->fullpath, data->pexport->id); 01855 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01856 return res_READDIR4.status; 01857 } 01858 01859 /* Get the attributes (costless: the attributes was cached when the root pentry was created */ 01860 if(cache_inode_getattr(pentry, 01861 &attr, 01862 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) 01863 { 01864 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01865 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get attributes for root pentry"); 01866 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01867 cache_inode_put(pentry); 01868 return res_READDIR4.status; 01869 } 01870 01871 /* Keep the pentry within the compound data */ 01872 if (data->current_entry) { 01873 cache_inode_put(data->current_entry); 01874 } 01875 data->current_entry = pentry; 01876 data->current_filetype = cache_inode_fsal_type_convert(attr.type); 01877 01878 /* redo the call on the other side of the junction */ 01879 return nfs4_op_readdir(op, data, resp); 01880 } 01881 01882 /* Allocation of the entries array */ 01883 if((entry_nfs_array = 01884 gsh_calloc(estimated_num_entries, sizeof(entry4))) == NULL) 01885 { 01886 LogError(COMPONENT_NFS_V4_PSEUDO, ERR_SYS, ERR_MALLOC, errno); 01887 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01888 return res_READDIR4.status; 01889 } 01890 01891 /* Cookie verifier has the value of the Server Boot Time for pseudo fs */ 01892 memset(cookie_verifier, 0, NFS4_VERIFIER_SIZE); 01893 #ifdef _WITH_COOKIE_VERIFIER 01894 /* BUGAZOMEU: management of the cookie verifier */ 01895 if(NFS_SpecificConfig.UseCookieVerf == 1) 01896 { 01897 memcpy(cookie_verifier, &ServerBootTime, sizeof(ServerBootTime)); 01898 if(cookie != 0) 01899 { 01900 if(memcmp(cookie_verifier, arg_READDIR4.cookieverf, NFS4_VERIFIER_SIZE) != 0) 01901 { 01902 res_READDIR4.status = NFS4ERR_BAD_COOKIE; 01903 gsh_free(entry_nfs_array); 01904 return res_READDIR4.status; 01905 } 01906 } 01907 } 01908 #endif 01909 /* Cookie delivered by the server and used by the client SHOULD not ne 0, 1 or 2 (cf RFC3530, page192) 01910 * because theses value are reserved for special use. 01911 * 0 - cookie for first READDIR 01912 * 1 - reserved for . on client handside 01913 * 2 - reserved for .. on client handside 01914 * Entries '.' and '..' are not returned also 01915 * For these reason, there will be an offset of 3 between NFS4 cookie and HPSS cookie */ 01916 01917 /* make sure to start at the right position given by the cookie */ 01918 iter = psfsentry.sons; 01919 if(cookie != 0) 01920 { 01921 for(; iter != NULL; iter = iter->next) 01922 if((iter->pseudo_id + 3) == cookie) 01923 break; 01924 } 01925 01926 /* Here, where are sure that iter is set to the position indicated eventually by the cookie */ 01927 i = 0; 01928 for(; iter != NULL; iter = iter->next) 01929 { 01930 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01931 "PSEUDO FS: Found entry %s", iter->name); 01932 01933 namelen = strlen(iter->name); 01934 entry_nfs_array[i].name.utf8string_len = namelen; 01935 if ((entry_nfs_array[i].name.utf8string_val = gsh_malloc(namelen + 1)) == NULL) 01936 { 01937 LogError(COMPONENT_NFS_V4_PSEUDO, ERR_SYS, ERR_MALLOC, errno); 01938 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01939 return res_READDIR4.status; 01940 } 01941 strncpy(entry_nfs_array[i].name.utf8string_val, iter->name, namelen); 01942 entry_nfs_array[i].name.utf8string_val[namelen] = '\0'; 01943 01944 entry_nfs_array[i].cookie = iter->pseudo_id + 3; 01945 01946 /* This used to be in an if with a bogus check for FATTR4_FILEHANDLE. Such 01947 * a common case, elected to set up FH for call to xxxx_ToFattr 01948 * unconditionally. 01949 */ 01950 if(entryFH.nfs_fh4_len == 0) 01951 { 01952 if(nfs4_AllocateFH(&entryFH) != NFS4_OK) 01953 { 01954 return res_READDIR4.status; 01955 } 01956 } 01957 /* Do the case where we stay within the pseudo file system. */ 01958 if(iter->junction_export == NULL) { 01959 01960 if(!nfs4_PseudoToFhandle(&entryFH, iter)) 01961 { 01962 res_READDIR4.status = NFS4ERR_SERVERFAULT; 01963 gsh_free(entry_nfs_array); 01964 return res_READDIR4.status; 01965 } 01966 01967 if(nfs4_PseudoToFattr(iter, 01968 &(entry_nfs_array[i].attrs), 01969 data, &entryFH, &(arg_READDIR4.attr_request)) != 0) 01970 { 01971 /* Should never occured, but the is no reason for leaving the section without any information */ 01972 entry_nfs_array[i].attrs.attrmask = RdAttrErrorBitmap; 01973 entry_nfs_array[i].attrs.attr_vals = RdAttrErrorVals; 01974 } 01975 } else { 01976 /* This is a junction. Code used to not recognize this which resulted 01977 * in readdir giving different attributes ( including FH, FSid, etc... ) 01978 * to clients from a lookup. AIX refused to list the directory because of 01979 * this. Now we go to the junction to get the attributes. 01980 */ 01981 LogFullDebug(COMPONENT_NFS_V4_PSEUDO, 01982 "PSEUDOFS READDIR : Offspring DIR #%s# id=%u is a junction full path %s ", 01983 iter->name, iter->junction_export->id, iter->junction_export->fullpath); 01984 /* Save the compound data context */ 01985 save_pexport = data->pexport; 01986 data->pexport = iter->junction_export; 01987 /* Build the credentials */ 01988 /* XXX Is this really necessary for doing a lookup and 01989 * getting attributes? 01990 * The logic is borrowed from the process invoked above in this code 01991 * when the target directory is a junction. 01992 */ 01993 if(nfs4_MakeCred(data) != 0) 01994 { 01995 LogMajor(COMPONENT_NFS_V4_PSEUDO, 01996 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get FSAL credentials for %s, id=%d", 01997 data->pexport->fullpath, data->pexport->id); 01998 res_READDIR4.status = NFS4ERR_WRONGSEC; 01999 return res_READDIR4.status; 02000 } 02001 /* Do the look up. */ 02002 if(FSAL_IS_ERROR 02003 ((fsal_status = 02004 FSAL_str2path(iter->junction_export->fullpath, (strlen(iter->junction_export->fullpath) +1 ), &exportpath_fsal)))) 02005 { 02006 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02007 return res_READDIR4.status; 02008 } 02009 if(FSAL_IS_ERROR(fsal_status = FSAL_lookupPath(&exportpath_fsal, 02010 data->pcontext, 02011 &fsal_handle, NULL))) 02012 { 02013 LogMajor(COMPONENT_NFS_V4_PSEUDO, 02014 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to lookup for %s , id=%d", 02015 data->pexport->fullpath, data->pexport->id); 02016 LogMajor(COMPONENT_NFS_V4_PSEUDO, 02017 "PSEUDO FS JUNCTION TRAVERSAL: fsal_status = ( %d, %d )", 02018 fsal_status.major, fsal_status.minor); 02019 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02020 return res_READDIR4.status; 02021 } 02022 /* Build the nfs4 handle. Again, we do this unconditionally. */ 02023 if(!nfs4_FSALToFhandle(&entryFH, &fsal_handle, data)) 02024 { 02025 LogMajor(COMPONENT_NFS_V4_PSEUDO, 02026 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to build the first file handle"); 02027 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02028 return res_READDIR4.status; 02029 } 02030 /* Add the entry to the cache as a root. There has to be a better way. */ 02031 fsdata.fh_desc.start = (caddr_t) &fsal_handle; 02032 fsdata.fh_desc.len = 0; 02033 FSAL_ExpandHandle(data->pcontext->export_context, 02034 FSAL_DIGEST_SIZEOF, 02035 &fsdata.fh_desc); 02036 if((pentry = cache_inode_make_root(&fsdata, 02037 data->pcontext, 02038 &cache_status)) == NULL) 02039 { 02040 LogMajor(COMPONENT_NFS_V4_PSEUDO, 02041 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Allocate root entry in cache inode failed, for %s, id=%d", 02042 data->pexport->fullpath, data->pexport->id); 02043 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02044 return res_READDIR4.status; 02045 } 02046 /* Finally, get the attributes */ 02047 if(cache_inode_getattr(pentry, 02048 &attr, 02049 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) 02050 { 02051 LogMajor(COMPONENT_NFS_V4_PSEUDO, 02052 "PSEUDO FS JUNCTION TRAVERSAL: /!\\ | Failed to get attributes for root pentry"); 02053 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02054 return res_READDIR4.status; 02055 } 02056 if(nfs4_FSALattr_To_Fattr(data->pexport, 02057 &attr, 02058 &(entry_nfs_array[i].attrs), 02059 data, &entryFH, &(arg_READDIR4.attr_request)) != 0) 02060 { 02061 /* Return the fattr4_rdattr_error , cf RFC3530, page 192 */ 02062 entry_nfs_array[i].attrs.attrmask = RdAttrErrorBitmap; 02063 entry_nfs_array[i].attrs.attr_vals = RdAttrErrorVals; 02064 } 02065 data->pexport = save_pexport; 02066 } 02067 /* Chain the entry together */ 02068 entry_nfs_array[i].nextentry = NULL; 02069 if(i != 0) 02070 entry_nfs_array[i - 1].nextentry = &(entry_nfs_array[i]); 02071 02072 /* Increment the counter */ 02073 i += 1; 02074 02075 /* Did we reach the maximum number of entries */ 02076 if(i == estimated_num_entries) 02077 break; 02078 } 02079 02080 /* Resize entry_nfs_array */ 02081 /* @todo : Is this reallocation actually needed ? */ 02082 #ifdef BUGAZOMEU 02083 if(i < estimated_num_entries) 02084 if((entry_nfs_array = gsh_realloc(entry_nfs_array, i * 02085 sizeof(entry4))) == NULL) 02086 { 02087 LogError(COMPONENT_NFS_V4_PSEUDO, ERR_SYS, ERR_MALLOC, errno); 02088 res_READDIR4.status = NFS4ERR_SERVERFAULT; 02089 gsh_free(entry_nfs_array); 02090 return res_READDIR4.status; 02091 } 02092 #endif 02093 /* Build the reply */ 02094 memcpy(res_READDIR4.READDIR4res_u.resok4.cookieverf, cookie_verifier, 02095 NFS4_VERIFIER_SIZE); 02096 if(i == 0) 02097 res_READDIR4.READDIR4res_u.resok4.reply.entries = NULL; 02098 else 02099 res_READDIR4.READDIR4res_u.resok4.reply.entries = entry_nfs_array; 02100 02101 /* did we reach the end ? */ 02102 if(iter == NULL) 02103 { 02104 /* Yes, we did */ 02105 res_READDIR4.READDIR4res_u.resok4.reply.eof = TRUE; 02106 } 02107 else 02108 { 02109 /* No, there are some more entries */ 02110 res_READDIR4.READDIR4res_u.resok4.reply.eof = FALSE; 02111 } 02112 02113 /* Exit properly */ 02114 res_READDIR4.status = NFS4_OK; 02115 02116 return NFS4_OK; 02117 } /* nfs4_op_readdir_pseudo */