nfs-ganesha 1.4

nfs_proto_tools.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 #ifdef _SOLARIS
00042 #include "solaris_port.h"
00043 #endif
00044 
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <pthread.h>
00048 #include <fcntl.h>
00049 #include <sys/file.h>           /* for having FNDELAY */
00050 #include <pwd.h>
00051 #include <grp.h>
00052 #include <stdint.h>
00053 #include "HashData.h"
00054 #include "HashTable.h"
00055 #include "log.h"
00056 #include "ganesha_rpc.h"
00057 #include "nfs23.h"
00058 #include "nfs4.h"
00059 #include "mount.h"
00060 #include "nfs_core.h"
00061 #include "cache_inode.h"
00062 #include "nfs_exports.h"
00063 #include "nfs_creds.h"
00064 #include "nfs_proto_functions.h"
00065 #include "nfs_tools.h"
00066 #include "nfs_file_handle.h"
00067 #include "nfs_proto_tools.h"
00068 #include "nfs4_acls.h"
00069 #ifdef _PNFS_MDS
00070 #include "sal_data.h"
00071 #include "sal_functions.h"
00072 #include "fsal.h"
00073 #include "fsal_pnfs.h"
00074 #include "pnfs_common.h"
00075 #endif /* _PNFS_MDS */
00076 
00077 #ifdef _USE_NFS4_ACL
00078 /* Define mapping of NFS4 who name and type. */
00079 static struct {
00080   char *string;
00081   int   stringlen;
00082   int type;
00083 } whostr_2_type_map[] = {
00084   {
00085     .string    = "OWNER@",
00086     .stringlen = sizeof("OWNER@") - 1,
00087     .type      = FSAL_ACE_SPECIAL_OWNER,
00088   },
00089   {
00090     .string    = "GROUP@",
00091     .stringlen = sizeof("GROUP@") - 1,
00092     .type      = FSAL_ACE_SPECIAL_GROUP,
00093   },
00094   {
00095     .string    = "EVERYONE@",
00096     .stringlen = sizeof("EVERYONE@") - 1,
00097     .type      = FSAL_ACE_SPECIAL_EVERYONE,
00098   },
00099 };
00100 #endif                          /* _USE_NFS4_ACL */
00101 
00102 /*
00103  * String representations of NFS protocol operations.
00104  */
00105 char *nfsv2_function_names[] = {
00106   "NFSv2_null", "NFSv2_getattr", "NFSv2_setattr", "NFSv2_root",
00107   "NFSv2_lookup", "NFSv2_readlink", "NFSv2_read", "NFSv2_writecache",
00108   "NFSv2_write", "NFSv2_create", "NFSv2_remove", "NFSv2_rename",
00109   "NFSv2_link", "NFSv2_symlink", "NFSv2_mkdir", "NFSv2_rmdir",
00110   "NFSv2_readdir", "NFSv2_statfs"
00111 };
00112 
00113 char *nfsv3_function_names[] = {
00114   "NFSv3_null", "NFSv3_getattr", "NFSv3_setattr", "NFSv3_lookup",
00115   "NFSv3_access", "NFSv3_readlink", "NFSv3_read", "NFSv3_write",
00116   "NFSv3_create", "NFSv3_mkdir", "NFSv3_symlink", "NFSv3_mknod",
00117   "NFSv3_remove", "NFSv3_rmdir", "NFSv3_rename", "NFSv3_link",
00118   "NFSv3_readdir", "NFSv3_readdirplus", "NFSv3_fsstat",
00119   "NFSv3_fsinfo", "NFSv3_pathconf", "NFSv3_commit"
00120 };
00121 
00122 char *nfsv4_function_names[] = {
00123   "NFSv4_null", "NFSv4_compound"
00124 };
00125 
00126 char *mnt_function_names[] = {
00127   "MNT_null", "MNT_mount", "MNT_dump", "MNT_umount", "MNT_umountall", "MNT_export"
00128 };
00129 
00130 char *rquota_functions_names[] = {
00131   "rquota_Null", "rquota_getquota", "rquota_getquotaspecific", "rquota_setquota",
00132   "rquota_setquotaspecific"
00133 };
00134 
00148 void nfs_FhandleToStr(u_long     rq_vers,
00149                       fhandle2  *pfh2,
00150                       nfs_fh3   *pfh3,
00151                       nfs_fh4   *pfh4,
00152                       char      *str)
00153 {
00154 
00155   switch (rq_vers)
00156     {
00157     case NFS_V4:
00158       sprint_fhandle4(str, pfh4);
00159       break;
00160 
00161     case NFS_V3:
00162       sprint_fhandle3(str, pfh3);
00163       break;
00164 
00165     case NFS_V2:
00166       sprint_fhandle2(str, pfh2);
00167       break;
00168     }
00169 }                               /* nfs_FhandleToStr */
00170 
00194 cache_entry_t *nfs_FhandleToCache(u_long rq_vers,
00195                                   fhandle2 * pfh2,
00196                                   nfs_fh3 * pfh3,
00197                                   nfs_fh4 * pfh4,
00198                                   nfsstat2 * pstatus2,
00199                                   nfsstat3 * pstatus3,
00200                                   nfsstat4 * pstatus4,
00201                                   fsal_attrib_list_t * pattr,
00202                                   fsal_op_context_t * pcontext,
00203                                   int *prc)
00204 {
00205   cache_inode_fsal_data_t fsal_data;
00206   cache_inode_status_t cache_status;
00207   cache_entry_t *pentry = NULL;
00208   fsal_attrib_list_t attr;
00209   exportlist_t *pexport = NULL;
00210   short exportid = 0;
00211 
00212   /* Default behaviour */
00213   *prc = NFS_REQ_OK;
00214 
00215   memset(&fsal_data, 0, sizeof(fsal_data));
00216   switch (rq_vers)
00217     {
00218     case NFS_V4:
00219       if(!nfs4_FhandleToFSAL(pfh4, &fsal_data.fh_desc, pcontext))
00220         {
00221           *prc = NFS_REQ_DROP;
00222           *pstatus4 = NFS4ERR_BADHANDLE;
00223           return NULL;
00224         }
00225       exportid = nfs4_FhandleToExportId(pfh4);
00226       break;
00227 
00228     case NFS_V3:
00229       if(!nfs3_FhandleToFSAL(pfh3, &fsal_data.fh_desc, pcontext))
00230         {
00231           *prc = NFS_REQ_DROP;
00232           *pstatus3 = NFS3ERR_BADHANDLE;
00233           return NULL;
00234         }
00235       exportid = nfs3_FhandleToExportId(pfh3);
00236       break;
00237 
00238     case NFS_V2:
00239       if(!nfs2_FhandleToFSAL(pfh2, &fsal_data.fh_desc, pcontext))
00240         {
00241           *prc = NFS_REQ_DROP;
00242           *pstatus2 = NFSERR_STALE;
00243           return NULL;
00244         }
00245       exportid = nfs2_FhandleToExportId(pfh2);
00246       break;
00247     }
00248 
00249   print_buff(COMPONENT_FILEHANDLE,
00250              fsal_data.fh_desc.start,
00251              fsal_data.fh_desc.len);
00252 
00253   if((pexport = nfs_Get_export_by_id(nfs_param.pexportlist, exportid)) == NULL)
00254     {
00255       /* invalid handle */
00256       switch (rq_vers)
00257         {
00258         case NFS_V4:
00259           *pstatus4 = NFS4ERR_STALE;
00260           break;
00261 
00262         case NFS_V3:
00263           *pstatus3 = NFS3ERR_STALE;
00264           break;
00265 
00266         case NFS_V2:
00267           *pstatus2 = NFSERR_STALE;
00268           break;
00269         }
00270       *prc = NFS_REQ_DROP;
00271 
00272       LogFullDebug(COMPONENT_NFSPROTO,
00273                    "Invalid file handle passed to nfsFhandleToCache ");
00274       return NULL;
00275     }
00276 
00277   if((pentry = cache_inode_get(&fsal_data, &attr, pcontext,
00278                                NULL, &cache_status)) == NULL)
00279     {
00280       switch (rq_vers)
00281         {
00282         case NFS_V4:
00283           *pstatus4 = NFS4ERR_STALE;
00284           break;
00285 
00286         case NFS_V3:
00287           *pstatus3 = NFS3ERR_STALE;
00288           break;
00289 
00290         case NFS_V2:
00291           *pstatus2 = NFSERR_STALE;
00292           break;
00293         }
00294       *prc = NFS_REQ_OK;
00295       return NULL;
00296     }
00297 
00298   if(pattr != NULL)
00299     *pattr = attr;
00300 
00301   return pentry;
00302 }                               /* nfs_FhandleToCache */
00303 
00315 int nfs_SetPostOpAttr(exportlist_t *pexport,
00316                       const fsal_attrib_list_t *pfsal_attr,
00317                       post_op_attr *presult)
00318 {
00319   if(pfsal_attr == NULL)
00320     {
00321       presult->attributes_follow
00322            = nfs3_FSALattr_To_Fattr(pexport,
00323                                     pfsal_attr,
00324                                     &(presult->post_op_attr_u.attributes));
00325     }
00326 
00327   if(nfs3_FSALattr_To_Fattr(pexport,
00328                             pfsal_attr,
00329                             &(presult->post_op_attr_u.attributes))
00330      == 0)
00331     presult->attributes_follow = FALSE;
00332   else
00333     presult->attributes_follow = TRUE;
00334 
00335   return 0;
00336 } /* nfs_SetPostOpAttr */
00337 
00350 void nfs_SetPreOpAttr(fsal_attrib_list_t * pfsal_attr, pre_op_attr * pattr)
00351 {
00352   if(pfsal_attr == NULL)
00353     {
00354       pattr->attributes_follow = FALSE;
00355     }
00356   else
00357     {
00358       pattr->pre_op_attr_u.attributes.size = pfsal_attr->filesize;
00359       pattr->pre_op_attr_u.attributes.mtime.seconds = pfsal_attr->mtime.seconds;
00360       pattr->pre_op_attr_u.attributes.mtime.nseconds = 0 ;
00361 
00362       pattr->pre_op_attr_u.attributes.ctime.seconds = pfsal_attr->ctime.seconds;
00363       pattr->pre_op_attr_u.attributes.ctime.nseconds = 0; 
00364 
00365       pattr->attributes_follow = TRUE;
00366     }
00367 }                               /* nfs_SetPreOpAttr */
00368 
00384 void nfs_SetWccData(exportlist_t * pexport,
00385                     fsal_attrib_list_t * pbefore_attr,
00386                     fsal_attrib_list_t * pafter_attr, wcc_data * pwcc_data)
00387 {
00388   /* Build directory pre operation attributes */
00389   nfs_SetPreOpAttr(pbefore_attr, &(pwcc_data->before));
00390 
00391   /* Build directory post operation attributes */
00392   nfs_SetPostOpAttr(pexport, pafter_attr, &(pwcc_data->after));
00393 }                               /* nfs_SetWccData */
00394 
00408 int nfs_RetryableError(cache_inode_status_t cache_status)
00409 {
00410   switch (cache_status)
00411     {
00412     case CACHE_INODE_IO_ERROR:
00413       if(nfs_param.core_param.drop_io_errors)
00414         {
00415           /* Drop the request */
00416           return TRUE;
00417         }
00418       else
00419         {
00420           /* Propagate error to the client */
00421           return FALSE;
00422         }
00423       break;
00424 
00425     case CACHE_INODE_INVALID_ARGUMENT:
00426       if(nfs_param.core_param.drop_inval_errors)
00427         {
00428           /* Drop the request */
00429           return TRUE;
00430         }
00431       else
00432         {
00433           /* Propagate error to the client */
00434           return FALSE;
00435         }
00436       break;
00437 
00438     case CACHE_INODE_DELAY:
00439       if(nfs_param.core_param.drop_delay_errors)
00440         {
00441           /* Drop the request */
00442           return TRUE;
00443         }
00444       else
00445         {
00446           /* Propagate error to the client */
00447           return FALSE;
00448         }
00449       break;
00450 
00451     case CACHE_INODE_SUCCESS:
00452       LogCrit(COMPONENT_NFSPROTO,
00453               "Possible implementation error: CACHE_INODE_SUCCESS managed as an error");
00454       return FALSE;
00455       break;
00456 
00457     case CACHE_INODE_MALLOC_ERROR:
00458     case CACHE_INODE_POOL_MUTEX_INIT_ERROR:
00459     case CACHE_INODE_GET_NEW_LRU_ENTRY:
00460     case CACHE_INODE_UNAPPROPRIATED_KEY:
00461     case CACHE_INODE_INIT_ENTRY_FAILED:
00462     case CACHE_INODE_FSAL_ERROR:
00463     case CACHE_INODE_LRU_ERROR:
00464     case CACHE_INODE_HASH_SET_ERROR:
00465     case CACHE_INODE_INCONSISTENT_ENTRY:
00466     case CACHE_INODE_HASH_TABLE_ERROR:
00467     case CACHE_INODE_INSERT_ERROR:
00468       /* Internal error, should be dropped and retryed */
00469       return TRUE;
00470       break;
00471 
00472     case CACHE_INODE_NOT_A_DIRECTORY:
00473     case CACHE_INODE_BAD_TYPE:
00474     case CACHE_INODE_ENTRY_EXISTS:
00475     case CACHE_INODE_DIR_NOT_EMPTY:
00476     case CACHE_INODE_NOT_FOUND:
00477     case CACHE_INODE_FSAL_EACCESS:
00478     case CACHE_INODE_IS_A_DIRECTORY:
00479     case CACHE_INODE_FSAL_EPERM:
00480     case CACHE_INODE_NO_SPACE_LEFT:
00481     case CACHE_INODE_CACHE_CONTENT_ERROR:
00482     case CACHE_INODE_CACHE_CONTENT_EXISTS:
00483     case CACHE_INODE_CACHE_CONTENT_EMPTY:
00484     case CACHE_INODE_READ_ONLY_FS:
00485     case CACHE_INODE_KILLED:
00486     case CACHE_INODE_FSAL_ESTALE:
00487     case CACHE_INODE_FSAL_ERR_SEC:
00488     case CACHE_INODE_QUOTA_EXCEEDED:
00489     case CACHE_INODE_NOT_SUPPORTED:
00490     case CACHE_INODE_NAME_TOO_LONG:
00491     case CACHE_INODE_STATE_CONFLICT:
00492     case CACHE_INODE_DEAD_ENTRY:
00493     case CACHE_INODE_ASYNC_POST_ERROR:
00494     case CACHE_INODE_STATE_ERROR:
00495     case CACHE_INODE_BAD_COOKIE:
00496     case CACHE_INODE_FILE_BIG:
00497     case CACHE_INODE_FILE_OPEN:
00498       /* Non retryable error, return error to client */
00499       return FALSE;
00500       break;
00501     }
00502 
00503   /* Should never reach this */
00504   LogDebug(COMPONENT_NFSPROTO,
00505            "cache_inode_status=%u not managed properly in nfs_RetryableError, line %u should never be reached",
00506            cache_status, __LINE__);
00507   return FALSE;
00508 }
00509 
00510 void nfs_SetFailedStatus(fsal_op_context_t * pcontext,
00511                          exportlist_t * pexport,
00512                          int version,
00513                          cache_inode_status_t status,
00514                          nfsstat2 * pstatus2,
00515                          nfsstat3 * pstatus3,
00516                          cache_entry_t * pentry0,
00517                          post_op_attr * ppost_op_attr,
00518                          cache_entry_t * pentry1,
00519                          fsal_attrib_list_t * ppre_vattr1,
00520                          wcc_data * pwcc_data1,
00521                          cache_entry_t * pentry2,
00522                          fsal_attrib_list_t * ppre_vattr2, wcc_data * pwcc_data2)
00523 {
00524   switch (version)
00525     {
00526     case NFS_V2:
00527       if(status != CACHE_INODE_SUCCESS) /* Should not use success to address a failed status */
00528         *pstatus2 = nfs2_Errno(status);
00529       break;
00530 
00531     case NFS_V3:
00532       if(status != CACHE_INODE_SUCCESS) /* Should not use success to address a failed status */
00533         *pstatus3 = nfs3_Errno(status);
00534 
00535       if(ppost_op_attr != NULL)
00536         nfs_SetPostOpAttr(pexport, NULL, ppost_op_attr);
00537 
00538       if(pwcc_data1 != NULL)
00539         nfs_SetWccData(pexport, ppre_vattr1, NULL, pwcc_data1);
00540 
00541       if(pwcc_data2 != NULL)
00542         nfs_SetWccData(pexport, ppre_vattr2, NULL, pwcc_data2);
00543       break;
00544 
00545     }
00546 }
00547 
00548 #ifdef _USE_NFS4_ACL
00549 /* Following idmapper function conventions, return 1 if successful, 0 otherwise. */
00550 static int nfs4_encode_acl_special_user(int who, char *attrvalsBuffer,
00551                                         u_int *LastOffset)
00552 {
00553   int rc = 0;
00554   int i;
00555   u_int utf8len = 0;
00556   u_int deltalen = 0;
00557 
00558   for (i = 0; i < FSAL_ACE_SPECIAL_EVERYONE; i++)
00559     {
00560       if (whostr_2_type_map[i].type == who)
00561         {
00562           if(whostr_2_type_map[i].stringlen % 4 == 0)
00563             deltalen = 0;
00564           else
00565             deltalen = 4 - whostr_2_type_map[i].stringlen % 4;
00566 
00567           utf8len = htonl(whostr_2_type_map[i].stringlen + deltalen);
00568           memcpy((char *)(attrvalsBuffer + *LastOffset), &utf8len, sizeof(int));
00569           *LastOffset += sizeof(int);
00570 
00571           memcpy((char *)(attrvalsBuffer + *LastOffset), whostr_2_type_map[i].string,
00572                  whostr_2_type_map[i].stringlen);
00573           *LastOffset += whostr_2_type_map[i].stringlen;
00574 
00575           /* Pad with zero to keep xdr alignement */
00576           if(deltalen != 0)
00577             memset((char *)(attrvalsBuffer + *LastOffset), 0, deltalen);
00578           *LastOffset += deltalen;
00579 
00580           /* Found a matched one. */
00581           rc = 1;
00582           break;
00583         }
00584     }
00585 
00586   return rc;
00587 }
00588 
00589 /* Following idmapper function conventions, return 1 if successful, 0 otherwise. */
00590 static int nfs4_encode_acl_group_name(fsal_gid_t gid, char *attrvalsBuffer,
00591                                       u_int *LastOffset)
00592 {
00593   int rc = 0;
00594   char name[MAXNAMLEN];
00595   u_int utf8len = 0;
00596   u_int stringlen = 0;
00597   u_int deltalen = 0;
00598 
00599   rc = gid2name(name, &gid);
00600   LogFullDebug(COMPONENT_NFS_V4,
00601                "encode gid2name = %s, strlen = %llu",
00602                name, (long long unsigned int)strlen(name));
00603   if(rc == 0)  /* Failure. */
00604     {
00605       /* Encode gid itself without @. */
00606       sprintf(name, "%u", gid);
00607     }
00608 
00609   stringlen = strlen(name);
00610   if(stringlen % 4 == 0)
00611     deltalen = 0;
00612   else
00613     deltalen = 4 - (stringlen % 4);
00614 
00615   utf8len = htonl(stringlen + deltalen);
00616   memcpy((char *)(attrvalsBuffer + *LastOffset), &utf8len, sizeof(int));
00617   *LastOffset += sizeof(int);
00618 
00619   memcpy((char *)(attrvalsBuffer + *LastOffset), name, stringlen);
00620   *LastOffset += stringlen;
00621 
00622   /* Pad with zero to keep xdr alignement */
00623   if(deltalen != 0)
00624     memset((char *)(attrvalsBuffer + *LastOffset), 0, deltalen);
00625   *LastOffset += deltalen;
00626 
00627   return rc;
00628 }
00629 
00630 /* Following idmapper function conventions, return 1 if successful, 0 otherwise. */
00631 static int nfs4_encode_acl_user_name(int whotype, fsal_uid_t uid,
00632                                      char *attrvalsBuffer, u_int *LastOffset)
00633 {
00634   int rc = 0;
00635   char name[MAXNAMLEN];
00636   u_int utf8len = 0;
00637   u_int stringlen = 0;
00638   u_int deltalen = 0;
00639 
00640   /* Encode special user first. */
00641   if (whotype != FSAL_ACE_NORMAL_WHO)
00642     {
00643       rc = nfs4_encode_acl_special_user(uid, attrvalsBuffer, LastOffset);
00644       if(rc == 1)  /* Success. */
00645         return rc;
00646     }
00647 
00648   /* Encode normal user or previous user we failed to encode as special user. */
00649   rc = uid2name(name, &uid);
00650   LogFullDebug(COMPONENT_NFS_V4,
00651                "econde uid2name = %s, strlen = %llu",
00652                name, (long long unsigned int)strlen(name));
00653   if(rc == 0)  /* Failure. */
00654     {
00655       /* Encode uid itself without @. */
00656       sprintf(name, "%u", uid);
00657     }
00658 
00659   stringlen = strlen(name);
00660   if(stringlen % 4 == 0)
00661     deltalen = 0;
00662   else
00663     deltalen = 4 - (stringlen % 4);
00664 
00665   utf8len = htonl(stringlen + deltalen);
00666   memcpy((char *)(attrvalsBuffer + *LastOffset), &utf8len, sizeof(int));
00667   *LastOffset += sizeof(int);
00668 
00669   memcpy((char *)(attrvalsBuffer + *LastOffset), name, stringlen);
00670   *LastOffset += stringlen;
00671 
00672   /* Pad with zero to keep xdr alignement */
00673   if(deltalen != 0)
00674     memset((char *)(attrvalsBuffer + *LastOffset), 0, deltalen);
00675   *LastOffset += deltalen;
00676 
00677   return rc;
00678 }
00679 
00680 /* Following idmapper function conventions, return 1 if successful, 0 otherwise. */
00681 static int nfs4_encode_acl(fsal_attrib_list_t * pattr, char *attrvalsBuffer, u_int *LastOffset)
00682 {
00683   int rc = 0;
00684   uint32_t naces, type, flag, access_mask, whotype;
00685   fsal_ace_t *pace;
00686 
00687   if(pattr->acl)
00688     {
00689       LogFullDebug(COMPONENT_NFS_V4,
00690                    "GATTR: Number of ACEs = %u",
00691                    pattr->acl->naces);
00692 
00693       /* Encode number of ACEs. */
00694       naces = htonl(pattr->acl->naces);
00695       memcpy((char *)(attrvalsBuffer + *LastOffset), &naces, sizeof(uint32_t));
00696       *LastOffset += sizeof(uint32_t);
00697 
00698       /* Encode ACEs. */
00699       for(pace = pattr->acl->aces; pace < pattr->acl->aces + pattr->acl->naces; pace++)
00700         {
00701           LogFullDebug(COMPONENT_NFS_V4,
00702                        "GATTR: type=0X%x, flag=0X%x, perm=0X%x",
00703                        pace->type, pace->flag, pace->perm);
00704 
00705           type = htonl(pace->type);
00706           flag = htonl(pace->flag);
00707           access_mask = htonl(pace->perm);
00708 
00709           memcpy((char *)(attrvalsBuffer + *LastOffset), &type, sizeof(uint32_t));
00710           *LastOffset += sizeof(uint32_t);
00711 
00712           memcpy((char *)(attrvalsBuffer + *LastOffset), &flag, sizeof(uint32_t));
00713           *LastOffset += sizeof(uint32_t);
00714 
00715           memcpy((char *)(attrvalsBuffer + *LastOffset), &access_mask, sizeof(uint32_t));
00716           *LastOffset += sizeof(uint32_t);
00717 
00718           if(IS_FSAL_ACE_GROUP_ID(*pace))  /* Encode group name. */
00719             {
00720               rc = nfs4_encode_acl_group_name(pace->who.gid, attrvalsBuffer, LastOffset);
00721             }
00722           else
00723             {
00724               if(!IS_FSAL_ACE_SPECIAL_ID(*pace))
00725                 {
00726                   whotype = FSAL_ACE_NORMAL_WHO;
00727                 }
00728               else
00729                 whotype = pace->who.uid;
00730 
00731               /* Encode special or normal user name. */
00732               rc = nfs4_encode_acl_user_name(whotype, pace->who.uid, attrvalsBuffer, LastOffset);
00733             }
00734 
00735           LogFullDebug(COMPONENT_NFS_V4,
00736                        "GATTR: special = %u, %s = %u",
00737                        IS_FSAL_ACE_SPECIAL_ID(*pace),
00738                        IS_FSAL_ACE_GROUP_ID(*pace) ? "gid" : "uid",
00739                        IS_FSAL_ACE_GROUP_ID(*pace) ? pace->who.gid : pace->who.uid);
00740 
00741         }
00742     }
00743   else
00744     {
00745       LogFullDebug(COMPONENT_NFS_V4,
00746                    "nfs4_encode_acl: no acl available");
00747 
00748       fattr4_acl acl;
00749       acl.fattr4_acl_len = htonl(0);
00750       memcpy((char *)(attrvalsBuffer + *LastOffset), &acl, sizeof(fattr4_acl));
00751       *LastOffset += fattr4tab[FATTR4_ACL].size_fattr4;
00752     }
00753 
00754   return rc;
00755 }
00756 #endif                          /* _USE_NFS4_ACL */
00757 
00758 static uint_t
00759 nfs_tools_xdr_utf8(utf8str_mixed *utf8, char *attrvalsBuffer)
00760 {
00761   u_int utf8len = 0;
00762   u_int deltalen = utf8->utf8string_len % 4;
00763   u_int LastOffset = 0;
00764 
00765   utf8len = htonl(utf8->utf8string_len);
00766   memcpy(attrvalsBuffer, &utf8len, sizeof(u_int));
00767   LastOffset += sizeof(u_int);
00768 
00769   memcpy(attrvalsBuffer + LastOffset,
00770          utf8->utf8string_val, utf8->utf8string_len);
00771   LastOffset += utf8->utf8string_len;
00772 
00773   /* Free what was allocated by uid2utf8 */
00774   gsh_free(utf8->utf8string_val);
00775 
00776   /* Pad with zero to keep xdr alignement */
00777   if(deltalen)
00778     {
00779       deltalen = 4 - deltalen;
00780       memset(attrvalsBuffer + LastOffset, 0, deltalen);
00781       LastOffset += deltalen;
00782     }
00783   return LastOffset;
00784 }
00785 
00786 void nfs4_Fattr_Free(fattr4 *fattr)
00787 {
00788   if(fattr->attrmask.bitmap4_val != NULL)
00789     {
00790       gsh_free(fattr->attrmask.bitmap4_val);
00791       fattr->attrmask.bitmap4_val = NULL;
00792     }
00793 
00794   if(fattr->attr_vals.attrlist4_val != NULL)
00795     {
00796       gsh_free(fattr->attr_vals.attrlist4_val);
00797       fattr->attr_vals.attrlist4_val = NULL;
00798     }
00799 }
00800 
00801 static int fsal_time_to_settime4(const fsal_time_t *ts, char *attrval)
00802 {
00803   time_how4 how = htonl(SET_TO_CLIENT_TIME4);
00804   int64_t sec = nfs_htonl64((int64_t)ts->seconds);
00805   uint32_t nsec = htonl(ts->nseconds);
00806   int LastOffset = 0;
00807 
00808   memcpy(attrval + LastOffset, &how, sizeof(how));
00809   LastOffset += sizeof(how);
00810   memcpy(attrval + LastOffset, &sec, sizeof(sec));
00811   LastOffset += sizeof(sec);
00812   memcpy(attrval + LastOffset, &nsec, sizeof(nsec));
00813   LastOffset += sizeof(uint32_t);
00814 
00815   return LastOffset;
00816 }
00817 
00818 int nfs4_supported_attrs_to_fattr(char *attrvalsBuffer)
00819 {
00820 #ifdef _USE_NFS4_1
00821   int lastbit = FATTR4_FS_CHARSET_CAP;
00822   unsigned int attrvalslist_supported[FATTR4_FS_CHARSET_CAP];
00823   uint32_t bitmap_val[3];
00824 #else
00825   int lastbit = FATTR4_MOUNTED_ON_FILEID;
00826   unsigned int attrvalslist_supported[FATTR4_MOUNTED_ON_FILEID];
00827   uint32_t bitmap_val[2];
00828 #endif
00829   int LastOffset = 0;
00830   fattr4_supported_attrs supported_attrs;
00831   uint32_t supported_attrs_len;
00832   uint32_t supported_attrs_val;
00833 
00834   /* The supported attributes have field ',supported' set in tab fattr4tab, I will proceed in 2 pass 
00835    * 1st: compute the number of supported attributes
00836    * 2nd: allocate the replyed bitmap and fill it
00837    *
00838    * I do not set a #define to keep the number of supported attributes because I want this parameter
00839    * to be a consequence of fattr4tab and avoid incoherency */
00840 
00841   /* How many supported attributes ? Compute the result in variable named c */
00842   int k, c = 0;
00843   for(k = FATTR4_SUPPORTED_ATTRS; k <= lastbit; k++)
00844     {
00845       if(fattr4tab[k].supported)
00846         attrvalslist_supported[c++] = k;
00847     }
00848 
00849   supported_attrs.bitmap4_val = bitmap_val;
00850   supported_attrs.bitmap4_len = sizeof(bitmap_val)/sizeof(bitmap_val[0]);
00851   nfs4_list_to_bitmap4(&supported_attrs, c, attrvalslist_supported);
00852 
00853   LogFullDebug(COMPONENT_NFS_V4,
00854                "Fattr (regular) supported_attrs(len)=%u -> %u|%u",
00855                supported_attrs.bitmap4_len, supported_attrs.bitmap4_val[0],
00856                supported_attrs.bitmap4_val[1]);
00857 
00858   /* we store the index */
00859   supported_attrs_len = htonl(supported_attrs.bitmap4_len);
00860   memcpy((char *)(attrvalsBuffer + LastOffset), &supported_attrs_len,
00861          sizeof(uint32_t));
00862   LastOffset += sizeof(uint32_t);
00863 
00864   /* And then the data */
00865   for(k = 0; k < supported_attrs.bitmap4_len; k++)
00866     {
00867       supported_attrs_val = htonl(supported_attrs.bitmap4_val[k]);
00868       memcpy((char *)(attrvalsBuffer + LastOffset), &supported_attrs_val,
00869              sizeof(uint32_t));
00870       LastOffset += sizeof(uint32_t);
00871     }
00872 
00873   return LastOffset;
00874 }
00875 
00876 int nfs4_Fattr_Fill(fattr4 *Fattr, int cnt, uint32_t *attrvalslist,
00877                     int LastOffset, char *attrvalsBuffer)
00878 {
00879   /* Set the bitmap for result */
00880   memset(Fattr, 0, sizeof(*Fattr));
00881   if((Fattr->attrmask.bitmap4_val = gsh_calloc(3, sizeof(uint32_t))) == NULL)
00882     return -1;
00883   Fattr->attrmask.bitmap4_len = 3;
00884   nfs4_list_to_bitmap4(&(Fattr->attrmask), cnt, attrvalslist);
00885 
00886   /* Set the attrlist4 */
00887   /* LastOffset contains the length of the attrvalsBuffer usefull data */
00888   Fattr->attr_vals.attrlist4_len = LastOffset;
00889   if(LastOffset != 0)           /* No need to allocate an empty buffer */
00890     {
00891       Fattr->attr_vals.attrlist4_val = gsh_malloc(LastOffset);
00892       if(Fattr->attr_vals.attrlist4_val == NULL)
00893         {
00894           gsh_free(Fattr->attrmask.bitmap4_val);
00895           return -1;
00896         }
00897       memcpy(Fattr->attr_vals.attrlist4_val, attrvalsBuffer,
00898              Fattr->attr_vals.attrlist4_len);
00899     }
00900   return 0;
00901 }
00922 int nfs4_FSALattr_To_Fattr(exportlist_t *pexport,
00923                            fsal_attrib_list_t *pattr,
00924                            fattr4 *Fattr,
00925                            compound_data_t *data,
00926                            nfs_fh4 *objFH,
00927                            bitmap4 *Bitmap)
00928 {
00929   fattr4_type file_type = 0;
00930   fattr4_link_support link_support;
00931   fattr4_symlink_support symlink_support;
00932   fattr4_fh_expire_type expire_type;
00933   fattr4_named_attr named_attr;
00934   fattr4_unique_handles unique_handles;
00935   fattr4_archive archive;
00936   fattr4_cansettime cansettime;
00937   fattr4_case_insensitive case_insensitive;
00938   fattr4_case_preserving case_preserving;
00939   fattr4_chown_restricted chown_restricted;
00940   fattr4_hidden hidden;
00941   fattr4_mode file_mode;
00942   fattr4_no_trunc no_trunc;
00943   fattr4_numlinks file_numlinks;
00944   fattr4_rawdev rawdev;
00945   fattr4_system system;
00946   fattr4_size file_size;
00947   fattr4_space_used file_space_used;
00948   fattr4_fsid fsid;
00949   fattr4_time_access time_access;
00950   fattr4_time_modify time_modify;
00951   fattr4_time_metadata time_metadata;
00952   fattr4_time_delta time_delta;
00953   fattr4_change file_change;
00954   fattr4_fileid file_id;
00955   fattr4_owner file_owner;
00956   fattr4_owner_group file_owner_group;
00957   fattr4_space_avail space_avail;
00958   fattr4_space_free space_free;
00959   fattr4_space_total space_total;
00960   fattr4_files_avail files_avail;
00961   fattr4_files_free files_free;
00962   fattr4_files_total files_total;
00963   fattr4_lease_time lease_time;
00964   fattr4_time_create time_create;
00965   fattr4_maxfilesize max_filesize;
00966   fattr4_maxread maxread;
00967   fattr4_maxwrite maxwrite;
00968   fattr4_maxname maxname;
00969   fattr4_maxlink maxlink;
00970   fattr4_homogeneous homogeneous;
00971   fattr4_aclsupport aclsupport;
00972 #ifndef _USE_NFS4_ACL
00973   fattr4_acl acl;
00974 #endif
00975   fattr4_rdattr_error rdattr_error;
00976   fattr4_quota_avail_hard quota_avail_hard;
00977   fattr4_quota_avail_soft quota_avail_soft;
00978   fattr4_quota_used quota_used;
00979 #ifdef _PNFS_MDS
00980   fattr4_layout_blksize layout_blksize;
00981 #endif /* _PNFS_MDS */
00982 
00983   u_int tmp_int;
00984   char tmp_buff[1024];
00985 
00986   uint32_t attribute_to_set = 0;
00987 
00988   u_int fhandle_len = 0;
00989   u_int LastOffset;
00990   u_int len = 0, off = 0;       /* Use for XDR alignment */
00991   int op_attr_success = 0;
00992 
00993 #ifdef _USE_NFS4_1
00994   uint32_t attrmasklist[FATTR4_FS_CHARSET_CAP]; /* List cannot be longer than FATTR4_FS_CHARSET_CAP */
00995   uint32_t attrvalslist[FATTR4_FS_CHARSET_CAP]; /* List cannot be longer than FATTR4_FS_CHARSET_CAP */
00996 #else
00997   uint32_t attrmasklist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
00998   uint32_t attrvalslist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
00999 #endif
01000   uint32_t attrmasklen = 0;
01001   char attrvalsBuffer[ATTRVALS_BUFFLEN];
01002 
01003   uint_t i = 0;
01004   uint_t j = 0;
01005 
01006   cache_inode_status_t cache_status;
01007 
01008   int statfscalled = 0;
01009   fsal_staticfsinfo_t * pstaticinfo = NULL ;
01010   fsal_dynamicfsinfo_t dynamicinfo;
01011 
01012   if( data != NULL )
01013     pstaticinfo = data->pcontext->export_context->fe_static_fs_info;
01014 
01015 #ifdef _USE_NFS4_ACL
01016   int rc;
01017 #endif
01018 
01019   /* basic init */
01020   memset(attrvalsBuffer, 0, NFS4_ATTRVALS_BUFFLEN);
01021 #ifdef _USE_NFS4_1
01022   memset((uint32_t *) attrmasklist, 0, FATTR4_FS_CHARSET_CAP * sizeof(uint32_t));
01023   memset((uint32_t *) attrvalslist, 0, FATTR4_FS_CHARSET_CAP * sizeof(uint32_t));
01024 #else
01025   memset((uint32_t *) attrmasklist, 0, FATTR4_MOUNTED_ON_FILEID * sizeof(uint32_t));
01026   memset((uint32_t *) attrvalslist, 0, FATTR4_MOUNTED_ON_FILEID * sizeof(uint32_t));
01027 #endif
01028 
01029   /* Convert the attribute bitmap to an attribute list */
01030   nfs4_bitmap4_to_list(Bitmap, &attrmasklen, attrmasklist);
01031 
01032   /* Once the bitmap has been converted to a list of attribute, manage each attribute */
01033   LastOffset = 0;
01034   j = 0;
01035 
01036   for(i = 0; i < attrmasklen; i++)
01037     {
01038       attribute_to_set = attrmasklist[i];
01039 
01040 #ifdef _USE_NFS4_1
01041       if(attrmasklist[i] > FATTR4_FS_CHARSET_CAP)
01042 #else
01043       if(attrmasklist[i] > FATTR4_MOUNTED_ON_FILEID)
01044 #endif
01045         {
01046           /* Erroneous value... skip */
01047           continue;
01048         }
01049       LogFullDebug(COMPONENT_NFS_V4,
01050                    "Flag for Operation (Regular) = %d|%d is ON,  name  = %s  reply_size = %d",
01051                    attrmasklist[i],
01052                    fattr4tab[attribute_to_set].val,
01053                    fattr4tab[attribute_to_set].name,
01054                    fattr4tab[attribute_to_set].size_fattr4);
01055 
01056       op_attr_success = 0;
01057 
01058       /* compute the new size for the fattr4 reply */
01059       /* This space is to be filled below in the big switch/case statement */
01060       switch (attribute_to_set)
01061         {
01062         case FATTR4_SUPPORTED_ATTRS:
01063           LastOffset += nfs4_supported_attrs_to_fattr(attrvalsBuffer + LastOffset);
01064 
01065           /* This kind of operation is always a success */
01066           op_attr_success = 1;
01067           break;
01068 
01069         case FATTR4_TYPE:
01070           switch (pattr->type)
01071             {
01072             case FSAL_TYPE_FILE:
01073             case FSAL_TYPE_XATTR:
01074               file_type = htonl(NF4REG);        /* Regular file */
01075               break;
01076 
01077             case FSAL_TYPE_DIR:
01078               file_type = htonl(NF4DIR);        /* Directory */
01079               break;
01080 
01081             case FSAL_TYPE_BLK:
01082               file_type = htonl(NF4BLK);        /* Special File - block device */
01083               break;
01084 
01085             case FSAL_TYPE_CHR:
01086               file_type = htonl(NF4CHR);        /* Special File - character device */
01087               break;
01088 
01089             case FSAL_TYPE_LNK:
01090               file_type = htonl(NF4LNK);        /* Symbolic Link */
01091               break;
01092 
01093             case FSAL_TYPE_SOCK:
01094               file_type = htonl(NF4SOCK);       /* Special File - socket */
01095               break;
01096 
01097             case FSAL_TYPE_FIFO:
01098               file_type = htonl(NF4FIFO);       /* Special File - fifo */
01099               break;
01100 
01101             case FSAL_TYPE_JUNCTION:
01102               /* For wanting of a better solution */
01103               file_type = 0;
01104               op_attr_success = 0;      /* This was no success */
01105               break;
01106             }                   /* switch( pattr->type ) */
01107 
01108           memcpy((char *)(attrvalsBuffer + LastOffset), &file_type, sizeof(fattr4_type));
01109           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01110           op_attr_success = 1;
01111           break;
01112 
01113         case FATTR4_FH_EXPIRE_TYPE:
01114           /* For the moment, we handle only the persistent filehandle */
01115           if(nfs_param.nfsv4_param.fh_expire == TRUE)
01116             expire_type = htonl(FH4_VOLATILE_ANY);
01117           else
01118             expire_type = htonl(FH4_PERSISTENT);
01119           memcpy((char *)(attrvalsBuffer + LastOffset), &expire_type,
01120                  sizeof(expire_type));
01121           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01122           op_attr_success = 1;
01123           break;
01124 
01125         case FATTR4_CHANGE:
01126           /* a value that change when the object change. I use the file's mtime */
01127           memset(&file_change, 0, sizeof(changeid4));
01128           file_change = nfs_htonl64((changeid4) pattr->change);
01129 
01130           memcpy((char *)(attrvalsBuffer + LastOffset), &file_change,
01131                  sizeof(fattr4_change));
01132           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01133           op_attr_success = 1;
01134           break;
01135 
01136         case FATTR4_SIZE:
01137           file_size = nfs_htonl64((fattr4_size) pattr->filesize);
01138           memcpy((char *)(attrvalsBuffer + LastOffset), &file_size, sizeof(fattr4_size));
01139           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01140           op_attr_success = 1;
01141           break;
01142 
01143         case FATTR4_LINK_SUPPORT:
01144           /* HPSS NameSpace support hard link */
01145           link_support = htonl(TRUE);
01146           memcpy((char *)(attrvalsBuffer + LastOffset), &link_support,
01147                  sizeof(fattr4_link_support));
01148           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01149           op_attr_success = 1;
01150           break;
01151 
01152         case FATTR4_SYMLINK_SUPPORT:
01153           /* HPSS NameSpace support symbolic link */
01154           symlink_support = htonl(TRUE);
01155           memcpy((char *)(attrvalsBuffer + LastOffset), &symlink_support,
01156                  sizeof(fattr4_symlink_support));
01157           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01158           op_attr_success = 1;
01159           break;
01160 
01161         case FATTR4_NAMED_ATTR:
01162           /* For this version of the binary, named attributes is not supported */
01163           named_attr = htonl(FALSE);
01164           memcpy((char *)(attrvalsBuffer + LastOffset), &named_attr,
01165                  sizeof(fattr4_named_attr));
01166           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01167           op_attr_success = 1;
01168           break;
01169 
01170         case FATTR4_FSID:
01171           /* The file system id (taken from the configuration file) */
01172           fsid.major = nfs_htonl64((uint64_t) pexport->filesystem_id.major);
01173           fsid.minor = nfs_htonl64((uint64_t) pexport->filesystem_id.minor);
01174 
01175           /* If object is a directory attached to a referral, then a different fsid is to be returned
01176            * to tell the client that a different fs is being crossed */
01177           if(nfs4_Is_Fh_Referral(objFH))
01178             {
01179               fsid.major = ~(nfs_htonl64((uint64_t) pexport->filesystem_id.major));
01180               fsid.minor = ~(nfs_htonl64((uint64_t) pexport->filesystem_id.minor));
01181             }
01182 
01183           memcpy((char *)(attrvalsBuffer + LastOffset), &fsid, sizeof(fattr4_fsid));
01184           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01185           op_attr_success = 1;
01186           break;
01187 
01188         case FATTR4_UNIQUE_HANDLES:
01189           /* Filehandles are unique */
01190           unique_handles = htonl(TRUE);
01191           memcpy((char *)(attrvalsBuffer + LastOffset), &unique_handles,
01192                  sizeof(fattr4_unique_handles));
01193           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01194           op_attr_success = 1;
01195           break;
01196 
01197         case FATTR4_LEASE_TIME:
01198           /* lease_time = htonl( (fattr4_lease_time)pstaticinfo->lease_time.seconds ) ; */
01199           lease_time = htonl(nfs_param.nfsv4_param.lease_lifetime);
01200           memcpy((char *)(attrvalsBuffer + LastOffset), &lease_time,
01201                  sizeof(fattr4_lease_time));
01202           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01203           op_attr_success = 1;
01204           break;
01205 
01206         case FATTR4_RDATTR_ERROR:
01207           rdattr_error = htonl(NFS4_OK);        /* By default, READDIR call may use a different value */
01208           memcpy((char *)(attrvalsBuffer + LastOffset), &rdattr_error,
01209                  sizeof(fattr4_rdattr_error));
01210           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01211           op_attr_success = 1;
01212           break;
01213 
01214         case FATTR4_ACL:
01215 #ifdef _USE_NFS4_ACL
01216           rc = nfs4_encode_acl(pattr, attrvalsBuffer, &LastOffset);
01217           if(rc == 0)  /* uid/gid mapping to a string failure */
01218             LogEvent(COMPONENT_NFS_V4, "Failed to map uid/gid to a string.");
01219 #else
01220           memset(&acl, 0, sizeof(acl));
01221           memcpy((char *)(attrvalsBuffer + LastOffset), &acl, sizeof(fattr4_acl));
01222           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01223 #endif
01224           op_attr_success = 1;
01225           break;
01226 
01227         case FATTR4_ACLSUPPORT:
01228 #ifdef _USE_NFS4_ACL
01229           aclsupport = htonl(ACL4_SUPPORT_ALLOW_ACL | ACL4_SUPPORT_DENY_ACL);
01230 #else
01231           aclsupport = htonl(0);
01232 #endif
01233           memcpy((char *)(attrvalsBuffer + LastOffset), &aclsupport,
01234                  sizeof(fattr4_aclsupport));
01235           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01236           op_attr_success = 1;
01237           break;
01238 
01239         case FATTR4_ARCHIVE:
01240           /* Archive flag is not supported */
01241           archive = htonl(FALSE);
01242           memcpy((char *)(attrvalsBuffer + LastOffset), &archive, sizeof(fattr4_archive));
01243           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01244           op_attr_success = 1;
01245           break;
01246 
01247         case FATTR4_CANSETTIME:
01248           /* The time can be set on files */
01249           cansettime = htonl(TRUE);
01250           memcpy((char *)(attrvalsBuffer + LastOffset), &cansettime,
01251                  sizeof(fattr4_cansettime));
01252           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01253           op_attr_success = 1;
01254           break;
01255 
01256         case FATTR4_CASE_INSENSITIVE:
01257           case_insensitive = htonl(pstaticinfo->case_insensitive);
01258           memcpy((char *)(attrvalsBuffer + LastOffset), &case_insensitive,
01259                  sizeof(fattr4_case_insensitive));
01260           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01261           op_attr_success = 1;
01262           break;
01263 
01264         case FATTR4_CASE_PRESERVING:
01265           case_preserving = htonl(pstaticinfo->case_preserving);
01266           memcpy((char *)(attrvalsBuffer + LastOffset), &case_preserving,
01267                  sizeof(fattr4_case_preserving));
01268           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01269           op_attr_success = 1;
01270           break;
01271 
01272         case FATTR4_CHOWN_RESTRICTED:
01273           /* chown is restricted to root */
01274           chown_restricted = htonl(pstaticinfo->chown_restricted);
01275           memcpy((char *)(attrvalsBuffer + LastOffset), &chown_restricted,
01276                  sizeof(fattr4_chown_restricted));
01277           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01278           op_attr_success = 1;
01279           break;
01280 
01281         case FATTR4_FILEHANDLE:
01282           /* Return the file handle */
01283           fhandle_len = htonl(objFH->nfs_fh4_len);
01284           memcpy((char *)(attrvalsBuffer + LastOffset), &fhandle_len, sizeof(u_int));
01285           LastOffset += sizeof(u_int);
01286 
01287           memcpy((char *)(attrvalsBuffer + LastOffset),
01288                  objFH->nfs_fh4_val, objFH->nfs_fh4_len);
01289           LastOffset += objFH->nfs_fh4_len;
01290 
01291           /* XDR's special stuff for 32-bit alignment */
01292           len = objFH->nfs_fh4_len;
01293           off = 0;
01294           while((len + off) % 4 != 0)
01295             {
01296               char c = '\0';
01297 
01298               off += 1;
01299               memset((char *)(attrvalsBuffer + LastOffset), (int)c, 1);
01300               LastOffset += 1;
01301             }
01302 
01303           op_attr_success = 1;
01304           break;
01305 
01306         case FATTR4_FILEID:
01307           /* The analog to the inode number. RFC3530 says "a number uniquely identifying the file within the filesystem" 
01308            * I use hpss_GetObjId to extract this information from the Name Server's handle */
01309           file_id = nfs_htonl64(pattr->fileid);
01310           memcpy((char *)(attrvalsBuffer + LastOffset), &file_id, sizeof(fattr4_fileid));
01311           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01312           op_attr_success = 1;
01313           break;
01314 
01315         case FATTR4_FILES_AVAIL:
01316           if(!statfscalled)
01317             {
01318               if((cache_status = cache_inode_statfs(data->current_entry,
01319                                                     &dynamicinfo,
01320                                                     data->pcontext,
01321                                                     &cache_status)) !=
01322                  CACHE_INODE_SUCCESS)
01323                 {
01324                   op_attr_success = 0;
01325                   break;
01326                 }
01327               else
01328                 statfscalled = 1;
01329             }
01330           files_avail = nfs_htonl64((fattr4_files_avail) dynamicinfo.avail_files);
01331           memcpy((char *)(attrvalsBuffer + LastOffset), &files_avail,
01332                  sizeof(fattr4_files_avail));
01333           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01334           op_attr_success = 1;
01335           break;
01336 
01337         case FATTR4_FILES_FREE:
01338           if(!statfscalled)
01339             {
01340               if((cache_status = cache_inode_statfs(data->current_entry,
01341                                                     &dynamicinfo,
01342                                                     data->pcontext,
01343                                                     &cache_status)) !=
01344                  CACHE_INODE_SUCCESS)
01345                 {
01346                   op_attr_success = 0;
01347                   break;
01348                 }
01349               else
01350                 statfscalled = 1;
01351             }
01352           files_free = nfs_htonl64((fattr4_files_avail) dynamicinfo.free_files);
01353           memcpy((char *)(attrvalsBuffer + LastOffset), &files_free,
01354                  sizeof(fattr4_files_free));
01355           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01356           op_attr_success = 1;
01357           break;
01358 
01359         case FATTR4_FILES_TOTAL:
01360           if(!statfscalled)
01361             {
01362               if((cache_status = cache_inode_statfs(data->current_entry,
01363                                                     &dynamicinfo,
01364                                                     data->pcontext,
01365                                                     &cache_status)) !=
01366                  CACHE_INODE_SUCCESS)
01367                 {
01368                   op_attr_success = 0;
01369                   break;
01370                 }
01371               else
01372                 statfscalled = 1;
01373             }
01374           files_total = nfs_htonl64((fattr4_files_avail) dynamicinfo.total_files);
01375           memcpy((char *)(attrvalsBuffer + LastOffset), &files_total,
01376                  sizeof(fattr4_files_total));
01377           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01378           op_attr_success = 1;
01379           break;
01380 
01381         case FATTR4_FS_LOCATIONS:
01382           if(data->current_entry->type != DIRECTORY)
01383             {
01384               op_attr_success = 0;
01385               break;
01386             }
01387 
01388           if(!nfs4_referral_str_To_Fattr_fs_location
01389              (data->current_entry->object.dir.referral, tmp_buff, &tmp_int))
01390             {
01391               op_attr_success = 0;
01392               break;
01393             }
01394 
01395           memcpy((char *)(attrvalsBuffer + LastOffset), tmp_buff, tmp_int);
01396           LastOffset += tmp_int;
01397           op_attr_success = 1;
01398           break;
01399 
01400         case FATTR4_HIDDEN:
01401           /* There are no hidden file in HPSS */
01402           hidden = htonl(FALSE);
01403           memcpy((char *)(attrvalsBuffer + LastOffset), &hidden, sizeof(fattr4_hidden));
01404           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01405           op_attr_success = 1;
01406           break;
01407 
01408         case FATTR4_HOMOGENEOUS:
01409           /* Unix semantic is homogeneous (all objects have the same kind of attributes) */
01410           homogeneous = htonl(TRUE);
01411           memcpy((char *)(attrvalsBuffer + LastOffset), &homogeneous,
01412                  sizeof(fattr4_homogeneous));
01413           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01414           op_attr_success = 1;
01415           break;
01416 
01417         case FATTR4_MAXFILESIZE:
01418           max_filesize = nfs_htonl64((fattr4_maxfilesize) FSINFO_MAX_FILESIZE);
01419           memcpy((char *)(attrvalsBuffer + LastOffset), &max_filesize,
01420                  sizeof(fattr4_maxfilesize));
01421           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01422           op_attr_success = 1;
01423           break;
01424 
01425         case FATTR4_MAXLINK:
01426           maxlink = htonl(pstaticinfo->maxlink);
01427           memcpy((char *)(attrvalsBuffer + LastOffset), &maxlink, sizeof(fattr4_maxlink));
01428           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01429           op_attr_success = 1;
01430           break;
01431 
01432         case FATTR4_MAXNAME:
01433           maxname = htonl((fattr4_maxname) pstaticinfo->maxnamelen);
01434           memcpy((char *)(attrvalsBuffer + LastOffset), &maxname, sizeof(fattr4_maxname));
01435           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01436           op_attr_success = 1;
01437           break;
01438 
01439         case FATTR4_MAXREAD:
01440           /* The exports.c MAXREAD-MAXWRITE code establishes these semantics: 
01441            *  a. If you set the MaxWrite and MaxRead defaults in an export file
01442            *  they apply. 
01443            *  b. If you set the MaxWrite and MaxRead defaults in the main.conf
01444            *  file they apply unless overwritten by an export file setting. 
01445            *  c. If no settings are present in the export file or the main.conf
01446            *  file then the defaults values in the FSAL apply. 
01447            */
01448 
01449           maxread = nfs_htonl64((fattr4_maxread) pexport->MaxRead );
01450           memcpy((char *)(attrvalsBuffer + LastOffset), &maxread, sizeof(fattr4_maxread));
01451           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01452           op_attr_success = 1;
01453           break;
01454 
01455         case FATTR4_MAXWRITE:
01456           maxwrite = nfs_htonl64((fattr4_maxwrite) pexport->MaxWrite );
01457           memcpy((char *)(attrvalsBuffer + LastOffset), &maxwrite,
01458                  sizeof(fattr4_maxwrite));
01459           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01460           op_attr_success = 1;
01461           break;
01462 
01463         case FATTR4_MIMETYPE:
01464           memset((char *)(attrvalsBuffer + LastOffset), 0,
01465                  sizeof(fattr4_mimetype));
01466           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01467           op_attr_success = 0;  /* No supported for the moment */
01468           break;
01469 
01470         case FATTR4_MODE:
01471           /* file_mode = (fattr4_mode) htonl(fsal2unix_mode(pattr->mode)) ; */
01472           file_mode = htonl((fattr4_mode) fsal2unix_mode(pattr->mode));
01473           memcpy((char *)(attrvalsBuffer + LastOffset), &file_mode, sizeof(fattr4_mode));
01474           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01475           op_attr_success = 1;
01476           break;
01477 
01478         case FATTR4_NO_TRUNC:
01479           /* File's names are not truncated, an error is returned is name is too long */
01480           no_trunc = htonl(pstaticinfo->no_trunc);
01481           memcpy((char *)(attrvalsBuffer + LastOffset), &no_trunc,
01482                  sizeof(fattr4_no_trunc));
01483           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01484           op_attr_success = 1;
01485           break;
01486 
01487         case FATTR4_NUMLINKS:
01488           /* Reply the number of links found in vattr structure */
01489           file_numlinks = htonl((fattr4_numlinks) pattr->numlinks);
01490           memcpy((char *)(attrvalsBuffer + LastOffset), &file_numlinks,
01491                  sizeof(fattr4_numlinks));
01492           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01493           op_attr_success = 1;
01494           break;
01495 
01496         case FATTR4_OWNER:
01497           /* Return the uid as a human readable utf8 string */
01498           if(uid2utf8(pattr->owner, &file_owner) == 0)
01499             {
01500               LastOffset += nfs_tools_xdr_utf8(&file_owner,
01501                                                (char *)(attrvalsBuffer + LastOffset));
01502               op_attr_success = 1;
01503             }
01504           else
01505             op_attr_success = 0;
01506           break;
01507 
01508         case FATTR4_OWNER_GROUP:
01509           /* Return the gid as a human-readable utf8 string */
01510           if(gid2utf8(pattr->group, &file_owner_group) == 0)
01511             {
01512               LastOffset += nfs_tools_xdr_utf8(&file_owner_group,
01513                                                (char *)(attrvalsBuffer + LastOffset));
01514               op_attr_success = 1;
01515             }
01516           else
01517             op_attr_success = 0;
01518           break;
01519 
01520         case FATTR4_QUOTA_AVAIL_HARD:
01521           quota_avail_hard = nfs_htonl64((fattr4_quota_avail_hard) NFS_V4_MAX_QUOTA_HARD);    
01522           memcpy((char *)(attrvalsBuffer + LastOffset), &quota_avail_hard,
01523                  sizeof(fattr4_quota_avail_hard));
01524           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01525           op_attr_success = 0;
01526           break;
01527 
01528         case FATTR4_QUOTA_AVAIL_SOFT:
01529           quota_avail_soft = nfs_htonl64((fattr4_quota_avail_soft) NFS_V4_MAX_QUOTA_SOFT);    
01530           memcpy((char *)(attrvalsBuffer + LastOffset), &quota_avail_soft,
01531                  sizeof(fattr4_quota_avail_soft));
01532           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01533           op_attr_success = 0;
01534           break;
01535 
01536         case FATTR4_QUOTA_USED:
01537           quota_used = nfs_htonl64((fattr4_quota_used) pattr->filesize);
01538           memcpy((char *)(attrvalsBuffer + LastOffset), &quota_used,
01539                  sizeof(fattr4_quota_used));
01540           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01541           op_attr_success = 0;
01542           break;
01543 
01544         case FATTR4_RAWDEV:
01545           rawdev.specdata1 = htonl(pattr->rawdev.major);
01546           rawdev.specdata2 = htonl(pattr->rawdev.minor);
01547           memcpy((char *)(attrvalsBuffer + LastOffset), &rawdev, sizeof(fattr4_rawdev));
01548           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01549           op_attr_success = 1;
01550           break;
01551 
01552         case FATTR4_SPACE_AVAIL:
01553           if(!statfscalled)
01554             {
01555               if((cache_status = cache_inode_statfs(data->current_entry,
01556                                                     &dynamicinfo,
01557                                                     data->pcontext,
01558                                                     &cache_status)) !=
01559                  CACHE_INODE_SUCCESS)
01560                 {
01561                   op_attr_success = 0;
01562                   break;
01563                 }
01564               else
01565                 statfscalled = 1;
01566             }
01567           space_avail = nfs_htonl64((fattr4_space_avail) dynamicinfo.avail_bytes);
01568           memcpy((char *)(attrvalsBuffer + LastOffset), &space_avail,
01569                  sizeof(fattr4_space_avail));
01570           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01571           op_attr_success = 1;
01572           break;
01573 
01574         case FATTR4_SPACE_FREE:
01575           if(!statfscalled)
01576             {
01577               if((cache_status = cache_inode_statfs(data->current_entry,
01578                                                     &dynamicinfo,
01579                                                     data->pcontext,
01580                                                     &cache_status)) !=
01581                  CACHE_INODE_SUCCESS)
01582                 {
01583                   op_attr_success = 0;
01584                   break;
01585                 }
01586               else
01587                 statfscalled = 1;
01588             }
01589           space_free = nfs_htonl64((fattr4_space_free) dynamicinfo.free_bytes);
01590           memcpy((char *)(attrvalsBuffer + LastOffset), &space_free,
01591                  sizeof(fattr4_space_free));
01592           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01593           op_attr_success = 1;
01594           break;
01595 
01596         case FATTR4_SPACE_TOTAL:
01597           if(!statfscalled)
01598             {
01599               if((cache_status = cache_inode_statfs(data->current_entry,
01600                                                     &dynamicinfo,
01601                                                     data->pcontext,
01602                                                     &cache_status)) !=
01603                  CACHE_INODE_SUCCESS)
01604                 {
01605                   op_attr_success = 0;
01606                   break;
01607                 }
01608               else
01609                 statfscalled = 1;
01610             }
01611           space_total = nfs_htonl64((fattr4_space_total) dynamicinfo.total_bytes);
01612           memcpy((char *)(attrvalsBuffer + LastOffset), &space_total,
01613                  sizeof(fattr4_space_total));
01614           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01615           op_attr_success = 1;
01616           break;
01617 
01618         case FATTR4_SPACE_USED:
01619           /* the number of bytes on the filesystem used by the object, which is slightly different 
01620            * from the file's size (there can be hole in the file) */
01621           file_space_used = nfs_htonl64((fattr4_space_used) pattr->spaceused);
01622           memcpy((char *)(attrvalsBuffer + LastOffset), &file_space_used,
01623                  sizeof(fattr4_space_used));
01624           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01625           op_attr_success = 1;
01626           break;
01627 
01628         case FATTR4_SYSTEM:
01629           /* This is not a windows system File-System with respect to the regarding API */
01630           system = htonl(FALSE);
01631           memcpy((char *)(attrvalsBuffer + LastOffset), &system, sizeof(fattr4_system));
01632           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01633           op_attr_success = 1;
01634           break;
01635 
01636         case FATTR4_TIME_ACCESS:
01637           /* This will contain the object's time os last access, the 'atime' in the Unix semantic */
01638           memset(&(time_access.seconds), 0, sizeof(int64_t));
01639           time_access.seconds = nfs_htonl64((int64_t) pattr->atime.seconds);
01640           time_access.nseconds = htonl((uint32_t) pattr->atime.nseconds);
01641           memcpy((char *)(attrvalsBuffer + LastOffset), &time_access,
01642                  fattr4tab[attribute_to_set].size_fattr4);
01643           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01644           op_attr_success = 1;
01645           break;
01646 
01647         case FATTR4_TIME_ACCESS_SET:
01648           LastOffset += fsal_time_to_settime4(&pattr->atime,
01649                                               attrvalsBuffer + LastOffset);
01650           op_attr_success = 1;
01651           break;
01652 
01653         case FATTR4_TIME_BACKUP:
01654           /* No time backup, return unix's beginning of time */
01655         case FATTR4_TIME_CREATE:
01656           /* No time create, return unix's beginning of time */
01657           time_create.seconds = nfs_htonl64(0LL);
01658           time_create.nseconds = htonl(0);
01659           memcpy((char *)(attrvalsBuffer + LastOffset), &time_create,
01660                  fattr4tab[attribute_to_set].size_fattr4);
01661           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01662           op_attr_success = 1;
01663           break;
01664 
01665         case FATTR4_TIME_DELTA:
01666           /* According to RFC3530, this is "the smallest usefull server time granularity", I set this to 1s */
01667           time_delta.seconds = nfs_htonl64(1LL);
01668           time_delta.nseconds = htonl(0);
01669           memcpy((char *)(attrvalsBuffer + LastOffset), &time_delta,
01670                  fattr4tab[attribute_to_set].size_fattr4);
01671           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01672           op_attr_success = 1;
01673           break;
01674 
01675         case FATTR4_TIME_METADATA:
01676           /* The time for the last metadata operation, the ctime in the unix's semantic */
01677           memset(&(time_metadata.seconds), 0, sizeof(int64_t));
01678           time_metadata.seconds = nfs_htonl64((int64_t) pattr->ctime.seconds);
01679           time_metadata.nseconds = htonl(pattr->ctime.nseconds);
01680           memcpy((char *)(attrvalsBuffer + LastOffset), &time_metadata,
01681                  fattr4tab[attribute_to_set].size_fattr4);
01682           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01683           op_attr_success = 1;
01684           break;
01685 
01686         case FATTR4_TIME_MODIFY:
01687           /* The time for the last modify operation, the mtime in the unix's semantic */
01688           memset(&(time_modify.seconds), 0, sizeof(int64_t));
01689           time_modify.seconds = nfs_htonl64((int64_t) pattr->mtime.seconds);
01690           time_modify.nseconds = htonl(pattr->mtime.nseconds);
01691 
01692           memcpy((char *)(attrvalsBuffer + LastOffset), &time_modify,
01693                  fattr4tab[attribute_to_set].size_fattr4);
01694           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01695           op_attr_success = 1;
01696           break;
01697 
01698         case FATTR4_TIME_MODIFY_SET:
01699           LastOffset += fsal_time_to_settime4(&pattr->mtime,
01700                                               attrvalsBuffer + LastOffset);
01701           op_attr_success = 1;
01702           break;
01703 
01704         case FATTR4_MOUNTED_ON_FILEID:
01705           file_id = nfs_htonl64(pattr->fileid);
01706           memcpy((char *)(attrvalsBuffer + LastOffset), &file_id, sizeof(fattr4_fileid));
01707           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01708           op_attr_success = 1;
01709           break;
01710 
01711 #ifdef _USE_NFS4_1
01712         case FATTR4_FS_LAYOUT_TYPES:
01713 #ifdef _PNFS_MDS
01714           *((uint32_t*)(attrvalsBuffer+LastOffset))
01715             = htonl(pstaticinfo->fs_layout_types
01716                     .fattr4_fs_layout_types_len);
01717 
01718           LastOffset += sizeof(uint32_t);
01719           for (k = 0; k < (pstaticinfo->fs_layout_types
01720                            .fattr4_fs_layout_types_len); k++)
01721             {
01722               *((layouttype4*)(attrvalsBuffer+LastOffset))
01723                 = htonl((pstaticinfo->fs_layout_types
01724                          .fattr4_fs_layout_types_val[k]));
01725               LastOffset += sizeof(layouttype4);
01726             }
01727 
01728           op_attr_success = 1;
01729           break;
01730 #endif /* _PNFS_MDS */
01731 
01732 #ifdef _PNFS_MDS
01733         case FATTR4_LAYOUT_BLKSIZE:
01734           layout_blksize
01735             = htonl((fattr4_layout_blksize) pstaticinfo->layout_blksize);
01736           memcpy((char *)(attrvalsBuffer + LastOffset),
01737                  &layout_blksize, sizeof(fattr4_layout_blksize));
01738           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
01739 
01740           op_attr_success = 1;
01741           break;
01742 #endif /* _PNFS_MDS */
01743 #endif /* _USE_NFS4_1 */
01744 
01745         default:
01746           LogFullDebug(COMPONENT_NFS_V4,
01747                        " unsupported value for attributes bitmap = %u", attribute_to_set);
01748 
01749           op_attr_success = 0;
01750           break;
01751         }                       /* switch( attribute_to_set ) */
01752 
01753       /* Increase the Offset for the next operation if this was a success */
01754       if(op_attr_success)
01755         {
01756           /* Set the returned bitmask */
01757           attrvalslist[j] = attribute_to_set;
01758           j += 1;
01759 
01760           /* Be carefull not to get out of attrvalsBuffer */
01761           if(LastOffset > ATTRVALS_BUFFLEN)
01762             return -1;
01763         }
01764 
01765     }                           /* for i */
01766 
01767   return nfs4_Fattr_Fill(Fattr, j, attrvalslist, LastOffset, attrvalsBuffer);
01768 }                               /* nfs4_FSALattr_To_Fattr */
01769 
01782 int nfs3_Sattr_To_FSALattr(fsal_attrib_list_t * pFSAL_attr,     /* Out: file attributes */
01783                            sattr3 * psattr)     /* In: file attributes  */
01784 {
01785   struct timeval t;
01786 
01787   if(pFSAL_attr == NULL || psattr == NULL)
01788     return 0;
01789 
01790   pFSAL_attr->asked_attributes = 0;
01791 
01792   if(psattr->mode.set_it == TRUE)
01793     {
01794       LogFullDebug(COMPONENT_NFSPROTO,
01795                    "nfs3_Sattr_To_FSALattr: mode = %o",
01796                    psattr->mode.set_mode3_u.mode);
01797       pFSAL_attr->mode = unix2fsal_mode(psattr->mode.set_mode3_u.mode);
01798       pFSAL_attr->asked_attributes |= FSAL_ATTR_MODE;
01799     }
01800 
01801   if(psattr->uid.set_it == TRUE)
01802     {
01803       LogFullDebug(COMPONENT_NFSPROTO,
01804                    "nfs3_Sattr_To_FSALattr: uid = %d",
01805                    psattr->uid.set_uid3_u.uid);
01806       pFSAL_attr->owner = psattr->uid.set_uid3_u.uid;
01807       pFSAL_attr->asked_attributes |= FSAL_ATTR_OWNER;
01808     }
01809 
01810   if(psattr->gid.set_it == TRUE)
01811     {
01812       LogFullDebug(COMPONENT_NFSPROTO,
01813                    "nfs3_Sattr_To_FSALattr: gid = %d",
01814                    psattr->gid.set_gid3_u.gid);
01815       pFSAL_attr->group = psattr->gid.set_gid3_u.gid;
01816       pFSAL_attr->asked_attributes |= FSAL_ATTR_GROUP;
01817     }
01818 
01819   if(psattr->size.set_it == TRUE)
01820     {
01821       LogFullDebug(COMPONENT_NFSPROTO,
01822                    "nfs3_Sattr_To_FSALattr: size = %lld",
01823                    psattr->size.set_size3_u.size);
01824       pFSAL_attr->filesize = (fsal_size_t) psattr->size.set_size3_u.size;
01825       pFSAL_attr->spaceused = (fsal_size_t) psattr->size.set_size3_u.size;
01826       /* Both FSAL_ATTR_SIZE and FSAL_ATTR_SPACEUSED are to be managed */
01827       pFSAL_attr->asked_attributes |= FSAL_ATTR_SIZE;
01828       pFSAL_attr->asked_attributes |= FSAL_ATTR_SPACEUSED;
01829     }
01830 
01831   if(psattr->atime.set_it != DONT_CHANGE)
01832     {
01833       LogFullDebug(COMPONENT_NFSPROTO,
01834                    "nfs3_Sattr_To_FSALattr: set=%d atime = %d,%d",
01835                    psattr->atime.set_it, psattr->atime.set_atime_u.atime.seconds,
01836                    psattr->atime.set_atime_u.atime.nseconds);
01837       if(psattr->atime.set_it == SET_TO_CLIENT_TIME)
01838         {
01839           pFSAL_attr->atime.seconds = psattr->atime.set_atime_u.atime.seconds;
01840           pFSAL_attr->atime.nseconds = 0;
01841         }
01842       else
01843         {
01844           /* Use the server's current time */
01845           gettimeofday(&t, NULL);
01846 
01847           pFSAL_attr->atime.seconds = t.tv_sec;
01848           pFSAL_attr->atime.nseconds = 0;
01849         }
01850       pFSAL_attr->asked_attributes |= FSAL_ATTR_ATIME;
01851     }
01852 
01853   if(psattr->mtime.set_it != DONT_CHANGE)
01854     {
01855       LogFullDebug(COMPONENT_NFSPROTO,
01856                    "nfs3_Sattr_To_FSALattr: set=%d mtime = %d",
01857                    psattr->atime.set_it, psattr->mtime.set_mtime_u.mtime.seconds ) ;
01858       if(psattr->mtime.set_it == SET_TO_CLIENT_TIME)
01859         {
01860           pFSAL_attr->mtime.seconds = psattr->mtime.set_mtime_u.mtime.seconds;
01861           pFSAL_attr->mtime.nseconds = 0 ;
01862         }
01863       else
01864         {
01865           /* Use the server's current time */
01866           gettimeofday(&t, NULL);
01867           pFSAL_attr->mtime.seconds = t.tv_sec;
01868           pFSAL_attr->mtime.nseconds = 0 ;
01869         }
01870       pFSAL_attr->asked_attributes |= FSAL_ATTR_MTIME;
01871     }
01872 
01873   return 1;
01874 }                               /* nfs3_Sattr_To_FSALattr */
01875 
01889 int nfs2_FSALattr_To_Fattr(exportlist_t * pexport,      /* In: the related export entry */
01890                            fsal_attrib_list_t * pFSAL_attr,     /* In: file attributes  */
01891                            fattr2 * pFattr)     /* Out: file attributes */
01892 {
01893   /* Badly formed arguments */
01894   if(pFSAL_attr == NULL || pFattr == NULL)
01895     return 0;
01896 
01897   /* @todo BUGAZOMEU: sanity check on attribute mask (does the FSAL support the attributes required to support NFSv2 ? */
01898 
01899   /* initialize mode */
01900   pFattr->mode = 0;
01901 
01902   switch (pFSAL_attr->type)
01903     {
01904     case FSAL_TYPE_FILE:
01905       pFattr->type = NFREG;
01906       pFattr->mode = NFS2_MODE_NFREG;
01907       break;
01908 
01909     case FSAL_TYPE_DIR:
01910       pFattr->type = NFDIR;
01911       pFattr->mode = NFS2_MODE_NFDIR;
01912       break;
01913 
01914     case FSAL_TYPE_BLK:
01915       pFattr->type = NFBLK;
01916       pFattr->mode = NFS2_MODE_NFBLK;
01917       break;
01918 
01919     case FSAL_TYPE_CHR:
01920       pFattr->type = NFCHR;
01921       pFattr->mode = NFS2_MODE_NFCHR;
01922       break;
01923 
01924     case FSAL_TYPE_FIFO:
01925       pFattr->type = NFFIFO;
01927       break;
01928 
01929     case FSAL_TYPE_LNK:
01930       pFattr->type = NFLNK;
01931       pFattr->mode = NFS2_MODE_NFLNK;
01932       break;
01933 
01934     case FSAL_TYPE_SOCK:
01935       pFattr->type = NFSOCK;
01937       break;
01938 
01939     case FSAL_TYPE_XATTR:
01940     case FSAL_TYPE_JUNCTION:
01941       pFattr->type = NFBAD;
01942     }
01943 
01944   pFattr->mode |= fsal2unix_mode(pFSAL_attr->mode);
01945   pFattr->nlink = pFSAL_attr->numlinks;
01946   pFattr->uid = pFSAL_attr->owner;
01947   pFattr->gid = pFSAL_attr->group;
01948 
01949   /* in NFSv2, it only keeps fsid.major, casted into an into an int32 */
01950   pFattr->fsid = (u_int) (pexport->filesystem_id.major & 0xFFFFFFFFLL);
01951 
01952   LogFullDebug(COMPONENT_NFSPROTO,
01953                "nfs2_FSALattr_To_Fattr: fsid.major = %#llX (%llu), fsid.minor = %#llX (%llu), nfs2_fsid = %#X (%u)",
01954                pexport->filesystem_id.major, pexport->filesystem_id.major,
01955                pexport->filesystem_id.minor, pexport->filesystem_id.minor, pFattr->fsid,
01956                pFattr->fsid);
01957 
01958   if(pFSAL_attr->filesize > NFS2_MAX_FILESIZE)
01959     pFattr->size = NFS2_MAX_FILESIZE;
01960   else
01961     pFattr->size = pFSAL_attr->filesize;
01962 
01963   pFattr->blocksize = DEV_BSIZE;
01964 
01965   pFattr->blocks = pFattr->size >> 9;   /* dividing by 512 */
01966   if(pFattr->size % DEV_BSIZE != 0)
01967     pFattr->blocks += 1;
01968 
01969   if(pFSAL_attr->type == FSAL_TYPE_CHR || pFSAL_attr->type == FSAL_TYPE_BLK)
01970     pFattr->rdev = pFSAL_attr->rawdev.major;
01971   else
01972     pFattr->rdev = 0;
01973 
01974   pFattr->atime.seconds = pFSAL_attr->atime.seconds;
01975   pFattr->atime.useconds = pFSAL_attr->atime.nseconds / 1000;
01976   pFattr->mtime.seconds = pFSAL_attr->mtime.seconds;
01977   pFattr->mtime.useconds = pFSAL_attr->mtime.nseconds / 1000;
01978   pFattr->ctime.seconds = pFSAL_attr->ctime.seconds;
01979   pFattr->ctime.useconds = pFSAL_attr->ctime.nseconds / 1000;
01980   pFattr->fileid = pFSAL_attr->fileid;
01981 
01982   return 1;
01983 }                               /*  nfs2_FSALattr_To_Fattr */
01984 
01997 int nfs4_SetCompoundExport(compound_data_t * data)
01998 {
01999   short exportid;
02000 
02001   /* This routine is not related to pseudo fs file handle, do not handle them */
02002   if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
02003     return NFS4_OK;
02004 
02005   /* Get the export id */
02006   if((exportid = nfs4_FhandleToExportId(&(data->currentFH))) == 0)
02007     return NFS4ERR_BADHANDLE;
02008 
02009   if((data->pexport = nfs_Get_export_by_id(data->pfullexportlist, exportid)) == NULL)
02010     return NFS4ERR_BADHANDLE;
02011 
02012   if((data->pexport->options & EXPORT_OPTION_NFSV4) == 0)
02013     return NFS4ERR_ACCESS;
02014 
02015   if(nfs4_MakeCred(data) != NFS4_OK)
02016     return NFS4ERR_WRONGSEC;
02017 
02018   return NFS4_OK;
02019 }                               /* nfs4_SetCompoundExport */
02020 
02033 int nfs4_FhandleToExId(nfs_fh4 * fh4p, unsigned short *ExIdp)
02034 {
02035   file_handle_v4_t *pfhandle4;
02036 
02037   /* Map the filehandle to the correct structure */
02038   pfhandle4 = (file_handle_v4_t *) (fh4p->nfs_fh4_val);
02039 
02040   /* The function should not be used on a pseudo fhandle */
02041   if(pfhandle4->pseudofs_flag == TRUE)
02042     return FALSE;
02043 
02044   *ExIdp = pfhandle4->exportid;
02045   return TRUE;
02046 }                               /* nfs4_FhandleToExId */
02047 
02048 /**** Glue related functions ****/
02049 
02063 void nfs4_stringid_split(char *buff, char *uidname, char *domainname)
02064 {
02065   char *c = NULL;
02066   unsigned int i = 0;
02067 
02068   for(c = buff, i = 0; *c != '\0'; c++, i++)
02069     if(*c == '@')
02070       break;
02071 
02072   strncpy(uidname, buff, i);
02073   uidname[i] = '\0';
02074   strcpy(domainname, c);
02075 
02076   LogFullDebug(COMPONENT_NFS_V4,
02077                "buff = #%s#    uid = #%s#   domain = #%s#",
02078                buff, uidname, domainname);
02079 }                               /* nfs4_stringid_split */
02080 
02088 void free_utf8(utf8string * utf8str)
02089 {
02090   if(utf8str != NULL)
02091     {
02092       if(utf8str->utf8string_val != NULL)
02093         gsh_free(utf8str->utf8string_val);
02094       utf8str->utf8string_val = 0;
02095       utf8str->utf8string_len = 0;
02096     }
02097 }
02098 
02109 int utf8dup(utf8string * newstr, utf8string * oldstr)
02110 {
02111   if(newstr == NULL)
02112     return -1;
02113 
02114   newstr->utf8string_len = oldstr->utf8string_len;
02115   newstr->utf8string_val = NULL;
02116 
02117   if(oldstr->utf8string_len == 0 || oldstr->utf8string_val == NULL)
02118     return 0;
02119 
02120   newstr->utf8string_val = gsh_malloc(oldstr->utf8string_len);
02121   if(newstr->utf8string_val == NULL)
02122     return -1;
02123 
02124   strncpy(newstr->utf8string_val, oldstr->utf8string_val, oldstr->utf8string_len);
02125 
02126   return 0;
02127 }                               /* uft82str */
02128 
02141 int utf82str(char *str, int size, utf8string * utf8str)
02142 {
02143   int copy;
02144 
02145   if(str == NULL)
02146     return -1;
02147 
02148   if(utf8str == NULL || utf8str->utf8string_len == 0)
02149     {
02150       str[0] = '\0';
02151       return -1;
02152     }
02153 
02154   if(utf8str->utf8string_len >= size)
02155     copy = size - 1;
02156   else
02157     copy = utf8str->utf8string_len;
02158 
02159   strncpy(str, utf8str->utf8string_val, copy);
02160   str[copy] = '\0';
02161 
02162   if(copy < utf8str->utf8string_len)
02163     return -1;
02164 
02165   return 0;
02166 }                               /* uft82str */
02167 
02180 int str2utf8(char *str, utf8string * utf8str)
02181 {
02182   uint_t len;
02183   char buff[MAXNAMLEN];
02184 
02185   /* The uft8 will probably be sent over XDR, for this reason, its size MUST be a multiple of 32 bits = 4 bytes */
02186   strcpy(buff, str);
02187   len = strlen(buff);
02188 
02189   /* BUGAZOMEU: TO BE DONE: use STUFF ALLOCATOR here */
02190   if(utf8str->utf8string_val == NULL)
02191     return -1;
02192 
02193   utf8str->utf8string_len = len;
02194   memcpy(utf8str->utf8string_val, buff, utf8str->utf8string_len);
02195   return 0;
02196 }                               /* str2utf8 */
02197 
02210 seqid4 nfs4_NextSeqId(seqid4 seqid)
02211 {
02212   return ((seqid + 1) % 0xFFFFFFFF);
02213 }                               /* nfs4_NextSeqId */
02214 
02229 /*
02230  * bitmap is usually 2 x uint32_t which makes a uint64_t
02231  *
02232  * Structure of the bitmap is as follow
02233  *
02234  *                  0         1
02235  *    +-------+---------+----------+-
02236  *    | count | 31 .. 0 | 63 .. 32 |
02237  *    +-------+---------+----------+-
02238  *
02239  * One bit is set for every possible attributes. The bits are packed together in a uint32_T (XDR alignment reason probably)
02240  * As said in the RFC3530, the n-th bit is with the uint32_t #(n/32), and its position with the uint32_t is n % 32
02241  * Example
02242  *     1st bit = FATTR4_TYPE            = 1
02243  *     2nd bit = FATTR4_LINK_SUPPORT    = 5
02244  *     3rd bit = FATTR4_SYMLINK_SUPPORT = 6
02245  *
02246  *     Juste one uint32_t is necessay: 2**1 + 2**5 + 2**6 = 2 + 32 + 64 = 98
02247  *   +---+----+
02248  *   | 1 | 98 |
02249  *   +---+----+
02250  *
02251  * Other Example
02252  *
02253  *     1st bit = FATTR4_LINK_SUPPORT    = 5
02254  *     2nd bit = FATTR4_SYMLINK_SUPPORT = 6
02255  *     3rd bit = FATTR4_MODE            = 33
02256  *     4th bit = FATTR4_OWNER           = 36
02257  *
02258  *     Two uint32_t will be necessary there:
02259  *            #1 = 2**5 + 2**6 = 32 + 64 = 96
02260  #            #2 = 2**(33-32) + 2**(36-32) = 2**1 + 2**4 = 2 + 16 = 18 
02261  *   +---+----+----+
02262  *   | 2 | 98 | 18 |
02263  *   +---+----+----+
02264  *
02265  */
02266 
02267 void nfs4_bitmap4_to_list(bitmap4 * b, uint_t * plen, uint32_t * pval)
02268 {
02269   uint_t i = 0;
02270   uint_t val = 0;
02271   uint_t index = 0;
02272   uint_t offset = 0;
02273   uint_t fattr4tabidx=0;
02274   if(b->bitmap4_len > 0)
02275     LogFullDebug(COMPONENT_NFS_V4, "Bitmap: Len = %u Val = %u|%u",
02276                  b->bitmap4_len, b->bitmap4_val[0], b->bitmap4_val[1]);
02277   else
02278     LogFullDebug(COMPONENT_NFS_V4, "Bitmap: Len = %u ... ", b->bitmap4_len);
02279 
02280   for(offset = 0; offset < b->bitmap4_len; offset++)
02281     {
02282       for(i = 0; i < 32; i++)
02283         {
02284           fattr4tabidx = i+32*offset;
02285 #ifdef _USE_NFS4_1
02286           if (fattr4tabidx > FATTR4_FS_CHARSET_CAP)
02287 #else
02288           if (fattr4tabidx > FATTR4_MOUNTED_ON_FILEID)
02289 #endif
02290              goto exit;
02291 
02292           val = 1 << i;         /* Compute 2**i */
02293           if(b->bitmap4_val[offset] & val)
02294             pval[index++] = fattr4tabidx;
02295         }
02296     }
02297 exit:
02298   *plen = index;
02299 
02300 }                               /* nfs4_bitmap4_to_list */
02301 
02316 /* bitmap is usually 2 x uint32_t which makes a uint64_t 
02317  * bitmap4_len is the number of uint32_t required to keep the bitmap value 
02318  *
02319  * Structure of the bitmap is as follow
02320  *
02321  *                  0         1
02322  *    +-------+---------+----------+-
02323  *    | count | 31 .. 0 | 63 .. 32 | 
02324  *    +-------+---------+----------+-
02325  *
02326  * One bit is set for every possible attributes. The bits are packed together in a uint32_T (XDR alignment reason probably)
02327  * As said in the RFC3530, the n-th bit is with the uint32_t #(n/32), and its position with the uint32_t is n % 32
02328  * Example
02329  *     1st bit = FATTR4_TYPE            = 1
02330  *     2nd bit = FATTR4_LINK_SUPPORT    = 5
02331  *     3rd bit = FATTR4_SYMLINK_SUPPORT = 6
02332  *
02333  *     Juste one uint32_t is necessay: 2**1 + 2**5 + 2**6 = 2 + 32 + 64 = 98
02334  *   +---+----+
02335  *   | 1 | 98 |
02336  *   +---+----+
02337  *
02338  * Other Example
02339  *
02340  *     1st bit = FATTR4_LINK_SUPPORT    = 5
02341  *     2nd bit = FATTR4_SYMLINK_SUPPORT = 6
02342  *     3rd bit = FATTR4_MODE            = 33
02343  *     4th bit = FATTR4_OWNER           = 36
02344  *
02345  *     Two uint32_t will be necessary there:
02346  *            #1 = 2**5 + 2**6 = 32 + 64 = 96
02347  #            #2 = 2**(33-32) + 2**(36-32) = 2**1 + 2**4 = 2 + 16 = 18 
02348  *   +---+----+----+
02349  *   | 2 | 98 | 18 |
02350  *   +---+----+----+
02351  *
02352  */
02353 
02354 /* This function converts a list of attributes to a bitmap4 structure */
02355 void nfs4_list_to_bitmap4(bitmap4 * b, uint_t plen, uint32_t * pval)
02356 {
02357   uint_t i;
02358   int maxpos =  -1;
02359 
02360   memset(b->bitmap4_val, 0, sizeof(uint32_t)*b->bitmap4_len);
02361 
02362   for(i = 0; i < plen; i++)
02363     {
02364       int intpos = pval[i] / 32;
02365       int bitpos = pval[i] % 32;
02366 
02367       if(intpos >= b->bitmap4_len)
02368         {
02369           LogCrit(COMPONENT_NFS_V4,
02370                   "Mismatch between bitmap len and the list: "
02371                   "got %d, need %d to accomodate attribute %d",
02372                   b->bitmap4_len, intpos+1, pval[i]);
02373           continue;
02374         }
02375       b->bitmap4_val[intpos] |= (1U << bitpos);
02376       if(intpos > maxpos)
02377         maxpos = intpos;
02378     }
02379 
02380   b->bitmap4_len = maxpos + 1;
02381   LogFullDebug(COMPONENT_NFS_V4, "Bitmap: Len = %u   Val = %u|%u|%u",
02382                b->bitmap4_len,
02383                b->bitmap4_len >= 1 ? b->bitmap4_val[0] : 0,
02384                b->bitmap4_len >= 2 ? b->bitmap4_val[1] : 0,
02385                b->bitmap4_len >= 3 ? b->bitmap4_val[2] : 0);
02386 }                               /* nfs4_list_to_bitmap4 */
02387 
02388 /*
02389  * Conversion of attributes
02390  */
02391 
02407 int 
02408 nfs3_FSALattr_To_PartialFattr(const fsal_attrib_list_t * FSAL_attr,
02409                               fsal_attrib_mask_t want,
02410                               fattr3 * Fattr)
02411 {
02412   if(FSAL_attr == NULL || Fattr == NULL)
02413     {
02414       LogFullDebug(COMPONENT_NFSPROTO,
02415                    "%s: FSAL_attr=%p, Fattr=%p",
02416                    __func__, FSAL_attr, Fattr);
02417       return 0;
02418     }
02419 
02420   if((FSAL_attr->asked_attributes & want) != want)
02421     {
02422       LogEvent(COMPONENT_NFSPROTO,
02423                    "%s: Caller wants 0x%llx, we only have 0x%llx - missing 0x%llx",
02424                    __func__, want, FSAL_attr->asked_attributes, 
02425                    (FSAL_attr->asked_attributes & want) ^ want);
02426       return 0;
02427     }
02428 
02429   if(FSAL_attr->asked_attributes & FSAL_ATTR_TYPE)
02430     {
02431       switch (FSAL_attr->type)
02432         {
02433         case FSAL_TYPE_FIFO:
02434           Fattr->type = NF3FIFO;
02435           break;
02436 
02437         case FSAL_TYPE_CHR:
02438           Fattr->type = NF3CHR;
02439           break;
02440 
02441         case FSAL_TYPE_DIR:
02442           Fattr->type = NF3DIR;
02443           break;
02444 
02445         case FSAL_TYPE_BLK:
02446           Fattr->type = NF3BLK;
02447           break;
02448 
02449         case FSAL_TYPE_FILE:
02450         case FSAL_TYPE_XATTR:
02451           Fattr->type = NF3REG;
02452           break;
02453 
02454         case FSAL_TYPE_LNK:
02455           Fattr->type = NF3LNK;
02456           break;
02457 
02458         case FSAL_TYPE_SOCK:
02459           Fattr->type = NF3SOCK;
02460           break;
02461 
02462         case FSAL_TYPE_JUNCTION:
02463           /* Should not occur */
02464           LogFullDebug(COMPONENT_NFSPROTO,
02465                        "nfs3_FSALattr_To_Fattr: FSAL_attr->type = %d",
02466                        FSAL_attr->type);
02467           Fattr->type = 0;
02468           return 0;
02469 
02470         default:
02471           LogEvent(COMPONENT_NFSPROTO,
02472                        "nfs3_FSALattr_To_Fattr: Bogus type = %d",
02473                        FSAL_attr->type);
02474           return 0;
02475         }
02476     }
02477 
02478   if(FSAL_attr->asked_attributes & FSAL_ATTR_MODE)
02479     Fattr->mode = fsal2unix_mode(FSAL_attr->mode);
02480   if(FSAL_attr->asked_attributes & FSAL_ATTR_NUMLINKS)
02481     Fattr->nlink = FSAL_attr->numlinks;
02482   if(FSAL_attr->asked_attributes & FSAL_ATTR_OWNER)
02483     Fattr->uid = FSAL_attr->owner;
02484   if(FSAL_attr->asked_attributes & FSAL_ATTR_GROUP)
02485     Fattr->gid = FSAL_attr->group;
02486   if(FSAL_attr->asked_attributes & FSAL_ATTR_SIZE)
02487     Fattr->size = FSAL_attr->filesize;
02488   if(FSAL_attr->asked_attributes & FSAL_ATTR_SPACEUSED)
02489     Fattr->used = FSAL_attr->spaceused;
02490   if(FSAL_attr->asked_attributes & FSAL_ATTR_RAWDEV)
02491     {
02492       Fattr->rdev.specdata1 = FSAL_attr->rawdev.major;
02493       Fattr->rdev.specdata2 = FSAL_attr->rawdev.minor;
02494     }
02495   if(FSAL_attr->asked_attributes & FSAL_ATTR_FILEID)
02496     Fattr->fileid = FSAL_attr->fileid;
02497   if(FSAL_attr->asked_attributes & FSAL_ATTR_ATIME)
02498     {
02499       Fattr->atime.seconds = FSAL_attr->atime.seconds;
02500       Fattr->atime.nseconds = FSAL_attr->atime.nseconds;
02501     }
02502   if(FSAL_attr->asked_attributes & FSAL_ATTR_MTIME)
02503     {
02504       Fattr->mtime.seconds = FSAL_attr->mtime.seconds;
02505       Fattr->mtime.nseconds = FSAL_attr->mtime.nseconds;
02506     }
02507   if(FSAL_attr->asked_attributes & FSAL_ATTR_CTIME)
02508     {
02509       Fattr->ctime.seconds = FSAL_attr->ctime.seconds;
02510       Fattr->ctime.nseconds = FSAL_attr->ctime.nseconds;
02511     }
02512 
02513   return 1;
02514 }                         /* nfs3_FSALattr_To_PartialFattr */
02515 
02531 int nfs3_FSALattr_To_Fattr(exportlist_t * pexport,      /* In: the related export entry */
02532                            const fsal_attrib_list_t * FSAL_attr,      /* In: file attributes */
02533                            fattr3 * Fattr)      /* Out: file attributes */
02534 {
02535   if(FSAL_attr == NULL || Fattr == NULL)
02536     {
02537       LogFullDebug(COMPONENT_NFSPROTO,
02538                    "nfs3_FSALattr_To_Fattr: FSAL_attr=%p, Fattr=%p",
02539                    FSAL_attr, Fattr);
02540       return 0;
02541     }
02542 
02543   if(!nfs3_FSALattr_To_PartialFattr(FSAL_attr, 
02544                                     FSAL_ATTR_TYPE| FSAL_ATTR_MODE | FSAL_ATTR_NUMLINKS |
02545                                     FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_SIZE |
02546                                     FSAL_ATTR_SPACEUSED | FSAL_ATTR_RAWDEV |
02547                                     FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME,
02548                                     Fattr))
02549     return 0;
02550 
02551   /* in NFSv3, we only keeps fsid.major, casted into an nfs_uint64 */
02552   Fattr->fsid = (nfs3_uint64) pexport->filesystem_id.major;
02553   LogFullDebug(COMPONENT_NFSPROTO,
02554                "%s: fsid.major = %#llX (%llu), fsid.minor = %#llX (%llu), nfs3_fsid = %#llX (%llu)",
02555                __func__,
02556                pexport->filesystem_id.major, pexport->filesystem_id.major,
02557                pexport->filesystem_id.minor, pexport->filesystem_id.minor, Fattr->fsid,
02558                Fattr->fsid);
02559   return 1;
02560 }
02561 
02574 int nfs2_Sattr_To_FSALattr(fsal_attrib_list_t * pFSAL_attr,     /* Out: file attributes */
02575                            sattr2 * Fattr)      /* In: file attributes */
02576 {
02577   struct timeval t;
02578 
02579   FSAL_CLEAR_MASK(pFSAL_attr->asked_attributes);
02580 
02581   if(Fattr->mode != (unsigned int)-1)
02582     {
02583       pFSAL_attr->mode = unix2fsal_mode(Fattr->mode);
02584       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_MODE);
02585     }
02586 
02587   if(Fattr->uid != (unsigned int)-1)
02588     {
02589       pFSAL_attr->owner = Fattr->uid;
02590       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_OWNER);
02591     }
02592 
02593   if(Fattr->gid != (unsigned int)-1)
02594     {
02595       pFSAL_attr->group = Fattr->gid;
02596       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_GROUP);
02597     }
02598 
02599   if(Fattr->size != (unsigned int)-1)
02600     {
02601       /* Both FSAL_ATTR_SIZE and FSAL_ATTR_SPACEUSED are to be managed */
02602       pFSAL_attr->filesize = (fsal_size_t) Fattr->size;
02603       pFSAL_attr->spaceused = (fsal_size_t) Fattr->size;
02604       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_SIZE);
02605       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_SPACEUSED);
02606     }
02607 
02608   /* if mtime.useconds == 1 millions,
02609    * this means we must set atime and mtime
02610    * to server time (NFS Illustrated p. 98)
02611    */
02612   if(Fattr->mtime.useconds == 1000000)
02613     {
02614       gettimeofday(&t, NULL);
02615 
02616       pFSAL_attr->atime.seconds = pFSAL_attr->mtime.seconds = t.tv_sec;
02617       pFSAL_attr->atime.nseconds = pFSAL_attr->mtime.nseconds = 0 ;
02618       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_ATIME);
02619       FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_MTIME);
02620     }
02621   else
02622     {
02623       /* set atime to client */
02624 
02625       if(Fattr->atime.seconds != (unsigned int)-1)
02626         {
02627           pFSAL_attr->atime.seconds = Fattr->atime.seconds;
02628 
02629           if(Fattr->atime.seconds != (unsigned int)-1)
02630             pFSAL_attr->atime.nseconds = Fattr->atime.useconds * 1000;
02631           else
02632             pFSAL_attr->atime.nseconds = 0;     /* ignored */
02633 
02634           FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_ATIME);
02635         }
02636 
02637       /* set mtime to client */
02638 
02639       if(Fattr->mtime.seconds != (unsigned int)-1)
02640         {
02641           pFSAL_attr->mtime.seconds = Fattr->mtime.seconds;
02642 
02643           if(Fattr->mtime.seconds != (unsigned int)-1)
02644             pFSAL_attr->mtime.nseconds = Fattr->mtime.useconds * 1000;
02645           else
02646             pFSAL_attr->mtime.nseconds = 0;     /* ignored */
02647 
02648           FSAL_SET_MASK(pFSAL_attr->asked_attributes, FSAL_ATTR_MTIME);
02649         }
02650     }
02651 
02652   return 1;
02653 }                               /* nfs2_Sattr_To_FSALattr */
02654 
02668 int nfs4_Fattr_Check_Access(fattr4 * Fattr, int access)
02669 {
02670   unsigned int i = 0;
02671 
02672   uint32_t attrmasklist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
02673   uint32_t attrmasklen = 0;
02674 
02675   /* Parameter sanity check */
02676   if(Fattr == NULL)
02677     return 0;
02678 
02679   if(access != FATTR4_ATTR_READ && access != FATTR4_ATTR_WRITE)
02680     return 0;
02681 
02682   /* Convert the attribute bitmap to an attribute list */
02683   nfs4_bitmap4_to_list(&(Fattr->attrmask), &attrmasklen, attrmasklist);
02684 
02685   for(i = 0; i < attrmasklen; i++)
02686     {
02687 #ifdef _USE_NFS4_1
02688       if(attrmasklist[i] > FATTR4_FS_CHARSET_CAP)
02689 #else
02690       if(attrmasklist[i] > FATTR4_MOUNTED_ON_FILEID)
02691 #endif
02692         {
02693           /* Erroneous value... skip */
02694           continue;
02695         }
02696 
02697       if(((int)fattr4tab[attrmasklist[i]].access & access) != access)
02698         return 0;
02699     }
02700 
02701   return 1;
02702 }                               /* nfs4_Fattr_Check_Access */
02703 
02717 int nfs4_Fattr_Check_Access_Bitmap(bitmap4 * pbitmap, int access)
02718 {
02719   unsigned int i = 0;
02720 #ifdef _USE_NFS4_1
02721 #define MAXATTR FATTR4_FS_CHARSET_CAP
02722 #else
02723 #define MAXATTR FATTR4_MOUNTED_ON_FILEID
02724 #endif
02725   uint32_t attrmasklist[MAXATTR];
02726   uint32_t attrmasklen = 0;
02727 
02728   /* Parameter sanity check */
02729   if(pbitmap == NULL)
02730     return 0;
02731 
02732   if(access != FATTR4_ATTR_READ && access != FATTR4_ATTR_WRITE)
02733     return 0;
02734 
02735   /* Convert the attribute bitmap to an attribute list */
02736   nfs4_bitmap4_to_list(pbitmap, &attrmasklen, attrmasklist);
02737 
02738   for(i = 0; i < attrmasklen; i++)
02739     {
02740       if(attrmasklist[i] > MAXATTR)
02741         {
02742           /* Erroneous value... skip */
02743           continue;
02744         }
02745 
02746       if(((int)fattr4tab[attrmasklist[i]].access & access) != access)
02747         return 0;
02748     }
02749 
02750   return 1;
02751 }                               /* nfs4_Fattr_Check_Access */
02752 
02764 int nfs4_bitmap4_Remove_Unsupported(bitmap4 * pbitmap )
02765 {
02766   uint_t i = 0;
02767   uint_t val = 0;
02768   uint_t offset = 0;
02769   uint fattr4tabidx = 0;
02770 
02771   uint32_t bitmap_val[3] ;
02772   bitmap4 bout ;
02773   int allsupp = 1;
02774 
02775   memset(bitmap_val, 0, 3 * sizeof(uint32_t));
02776 
02777   bout.bitmap4_val = bitmap_val ;
02778   bout.bitmap4_len = pbitmap->bitmap4_len  ;
02779 
02780   if(pbitmap->bitmap4_len > 0)
02781     LogFullDebug(COMPONENT_NFS_V4, "Bitmap: Len = %u Val = %u|%u",
02782                  pbitmap->bitmap4_len, pbitmap->bitmap4_val[0],
02783                  pbitmap->bitmap4_val[1]);
02784   else
02785     LogFullDebug(COMPONENT_NFS_V4, "Bitmap: Len = %u ... ",
02786                  pbitmap->bitmap4_len);
02787 
02788   for(offset = 0; offset < pbitmap->bitmap4_len; offset++)
02789     {
02790       for(i = 0; i < 32; i++)
02791         {
02792           fattr4tabidx = i+32*offset;
02793 #ifdef _USE_NFS4_1
02794           if (fattr4tabidx > FATTR4_FS_CHARSET_CAP)
02795 #else
02796           if (fattr4tabidx > FATTR4_MOUNTED_ON_FILEID)
02797 #endif
02798              goto exit;
02799 
02800           val = 1 << i;         /* Compute 2**i */
02801           if(pbitmap->bitmap4_val[offset] & val)
02802            {
02803              if( fattr4tab[fattr4tabidx].supported ) /* keep only supported stuff */
02804                bout.bitmap4_val[offset] |= val ;
02805            }
02806         }
02807     }
02808 
02809 exit:
02810   memcpy(pbitmap->bitmap4_val, bout.bitmap4_val,
02811          bout.bitmap4_len * sizeof(uint32_t));
02812 
02813   return allsupp;
02814 }                               /* nfs4_Fattr_Bitmap_Remove_Unsupported */
02815 
02816 
02829 int nfs4_Fattr_Supported(fattr4 * Fattr)
02830 {
02831   unsigned int i = 0;
02832 
02833   uint32_t attrmasklist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
02834   uint32_t attrmasklen = 0;
02835 
02836   /* Parameter sanity check */
02837   if(Fattr == NULL)
02838     return 0;
02839 
02840   /* Convert the attribute bitmap to an attribute list */
02841   nfs4_bitmap4_to_list(&(Fattr->attrmask), &attrmasklen, attrmasklist);
02842 
02843   for(i = 0; i < attrmasklen; i++)
02844     {
02845 
02846 #ifndef _USE_NFS4_1
02847       if(attrmasklist[i] > FATTR4_MOUNTED_ON_FILEID)
02848         {
02849           /* Erroneous value... skip */
02850           continue;
02851         }
02852 #endif
02853 
02854       LogFullDebug(COMPONENT_NFS_V4,
02855                    "nfs4_Fattr_Supported  ==============> %s supported flag=%u | ",
02856                    fattr4tab[attrmasklist[i]].name, fattr4tab[attrmasklist[i]].supported);
02857 
02858       if(!fattr4tab[attrmasklist[i]].supported)
02859         return 0;
02860     }
02861 
02862   return 1;
02863 }                               /* nfs4_Fattr_Supported */
02864 
02877 int nfs4_Fattr_Supported_Bitmap(bitmap4 * pbitmap)
02878 {
02879   unsigned int i = 0;
02880 
02881   uint32_t attrmasklist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
02882   uint32_t attrmasklen = 0;
02883 
02884   /* Parameter sanity check */
02885   if(pbitmap == NULL)
02886     return 0;
02887 
02888   /* Convert the attribute bitmap to an attribute list */
02889   nfs4_bitmap4_to_list(pbitmap, &attrmasklen, attrmasklist);
02890 
02891   for(i = 0; i < attrmasklen; i++)
02892     {
02893 
02894 #ifndef _USE_NFS4_1
02895       if(attrmasklist[i] > FATTR4_MOUNTED_ON_FILEID)
02896         {
02897           /* Erroneous value... skip */
02898           continue;
02899         }
02900 #endif
02901       
02902       LogFullDebug(COMPONENT_NFS_V4,
02903                    "nfs4_Fattr_Supported  ==============> %s supported flag=%u",
02904                    fattr4tab[attrmasklist[i]].name,
02905                    fattr4tab[attrmasklist[i]].supported);
02906       if(!fattr4tab[attrmasklist[i]].supported)
02907         return 0;
02908     }
02909 
02910   return 1;
02911 }                               /* nfs4_Fattr_Supported */
02912 
02925 int nfs4_Fattr_cmp(fattr4 * Fattr1, fattr4 * Fattr2)
02926 {
02927   uint32_t attrmasklist1[FATTR4_MOUNTED_ON_FILEID];     /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
02928   uint32_t attrmasklen1 = 0;
02929   u_int LastOffset;
02930   uint32_t attrmasklist2[FATTR4_MOUNTED_ON_FILEID];     /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
02931   uint32_t attrmasklen2 = 0;
02932   uint32_t i;
02933   uint32_t k;
02934   unsigned int cmp = 0;
02935   u_int len = 0;
02936   uint32_t attribute_to_set = 0;
02937 
02938   if(Fattr1 == NULL)
02939     return FALSE;
02940 
02941   if(Fattr2 == NULL)
02942     return FALSE;
02943 
02944   if(Fattr1->attrmask.bitmap4_len != Fattr2->attrmask.bitmap4_len)      /* different mask */
02945     return FALSE;
02946 
02947   /* Convert the attribute bitmap to an attribute list */
02948   nfs4_bitmap4_to_list(&(Fattr1->attrmask), &attrmasklen1, attrmasklist1);
02949   nfs4_bitmap4_to_list(&(Fattr2->attrmask), &attrmasklen2, attrmasklist2);
02950 
02951   /* Should not occur, bu this is a sanity check */
02952   if(attrmasklen1 != attrmasklen2)
02953     return FALSE;
02954 
02955   for(i = 0; i < attrmasklen1; i++)
02956     {
02957       if(attrmasklist1[i] != attrmasklist2[i])
02958         return 0;
02959 
02960       if(attrmasklist1[i] == FATTR4_RDATTR_ERROR)
02961         return -1;
02962 
02963       if(attrmasklist2[i] == FATTR4_RDATTR_ERROR)
02964         return -1;
02965     }
02966 
02967   cmp = 0;
02968   LastOffset = 0;
02969   len = 0;
02970 
02971   for(i = 0; i < attrmasklen1; i++)
02972     {
02973       attribute_to_set = attrmasklist1[i];
02974 
02975       LogFullDebug(COMPONENT_NFS_V4,
02976                    "nfs4_Fattr_cmp ==============> %s",
02977                    fattr4tab[attribute_to_set].name);
02978 
02979       switch (attribute_to_set)
02980         {
02981         case FATTR4_SUPPORTED_ATTRS:
02982           memcpy(&len, (char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
02983                  sizeof(u_int));
02984           cmp +=
02985               memcmp((char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
02986                      (char *)(Fattr2->attr_vals.attrlist4_val + LastOffset),
02987                      sizeof(u_int));
02988 
02989           len = htonl(len);
02990           LastOffset += sizeof(u_int);
02991 
02992           for(k = 0; k < len; k++)
02993             {
02994               cmp += memcmp((char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
02995                             (char *)(Fattr2->attr_vals.attrlist4_val + LastOffset),
02996                             sizeof(uint32_t));
02997               LastOffset += sizeof(uint32_t);
02998             }
02999 
03000           break;
03001 
03002         case FATTR4_FILEHANDLE:
03003         case FATTR4_OWNER:
03004         case FATTR4_OWNER_GROUP:
03005           memcpy(&len, (char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
03006                  sizeof(u_int));
03007           len = ntohl(len);     /* xdr marshalling on fattr4 */
03008           cmp += memcmp((char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
03009                         (char *)(Fattr2->attr_vals.attrlist4_val + LastOffset),
03010                         sizeof(u_int));
03011           LastOffset += sizeof(u_int);
03012           cmp += memcmp((char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
03013                         (char *)(Fattr2->attr_vals.attrlist4_val + LastOffset), len);
03014           break;
03015 
03016         case FATTR4_TYPE:
03017         case FATTR4_FH_EXPIRE_TYPE:
03018         case FATTR4_CHANGE:
03019         case FATTR4_SIZE:
03020         case FATTR4_LINK_SUPPORT:
03021         case FATTR4_SYMLINK_SUPPORT:
03022         case FATTR4_NAMED_ATTR:
03023         case FATTR4_FSID:
03024         case FATTR4_UNIQUE_HANDLES:
03025         case FATTR4_LEASE_TIME:
03026         case FATTR4_RDATTR_ERROR:
03027         case FATTR4_ACL:
03028         case FATTR4_ACLSUPPORT:
03029         case FATTR4_ARCHIVE:
03030         case FATTR4_CANSETTIME:
03031         case FATTR4_CASE_INSENSITIVE:
03032         case FATTR4_CASE_PRESERVING:
03033         case FATTR4_CHOWN_RESTRICTED:
03034         case FATTR4_FILEID:
03035         case FATTR4_FILES_AVAIL:
03036         case FATTR4_FILES_FREE:
03037         case FATTR4_FILES_TOTAL:
03038         case FATTR4_FS_LOCATIONS:
03039         case FATTR4_HIDDEN:
03040         case FATTR4_HOMOGENEOUS:
03041         case FATTR4_MAXFILESIZE:
03042         case FATTR4_MAXLINK:
03043         case FATTR4_MAXNAME:
03044         case FATTR4_MAXREAD:
03045         case FATTR4_MAXWRITE:
03046         case FATTR4_MIMETYPE:
03047         case FATTR4_MODE:
03048         case FATTR4_NO_TRUNC:
03049         case FATTR4_NUMLINKS:
03050         case FATTR4_QUOTA_AVAIL_HARD:
03051         case FATTR4_QUOTA_AVAIL_SOFT:
03052         case FATTR4_QUOTA_USED:
03053         case FATTR4_RAWDEV:
03054         case FATTR4_SPACE_AVAIL:
03055         case FATTR4_SPACE_FREE:
03056         case FATTR4_SPACE_TOTAL:
03057         case FATTR4_SPACE_USED:
03058         case FATTR4_SYSTEM:
03059         case FATTR4_TIME_ACCESS:
03060         case FATTR4_TIME_ACCESS_SET:
03061         case FATTR4_TIME_BACKUP:
03062         case FATTR4_TIME_CREATE:
03063         case FATTR4_TIME_DELTA:
03064         case FATTR4_TIME_METADATA:
03065         case FATTR4_TIME_MODIFY:
03066         case FATTR4_TIME_MODIFY_SET:
03067         case FATTR4_MOUNTED_ON_FILEID:
03068           cmp += memcmp((char *)(Fattr1->attr_vals.attrlist4_val + LastOffset),
03069                         (char *)(Fattr2->attr_vals.attrlist4_val + LastOffset),
03070                         fattr4tab[attribute_to_set].size_fattr4);
03071           break;
03072 
03073         default:
03074           return 0;
03075           break;
03076         }
03077     }
03078   if(cmp == 0)
03079     return TRUE;
03080   else
03081     return FALSE;
03082 }
03083 
03084 #ifdef _USE_NFS4_ACL
03085 static int nfs4_decode_acl_special_user(utf8string *utf8str, int *who)
03086 {
03087   int i;
03088 
03089   for (i = 0; i < FSAL_ACE_SPECIAL_EVERYONE; i++)
03090     {
03091       if(strncmp(utf8str->utf8string_val, whostr_2_type_map[i].string, utf8str->utf8string_len) == 0)
03092         {
03093           *who = whostr_2_type_map[i].type;
03094           return 0;
03095         }
03096     }
03097 
03098   return -1;
03099 }
03100 
03101 static int nfs4_decode_acl(fsal_attrib_list_t * pFSAL_attr, fattr4 * Fattr, u_int *LastOffset)
03102 {
03103   fsal_acl_status_t status;
03104   fsal_acl_data_t acldata;
03105   fsal_ace_t *pace;
03106   fsal_acl_t *pacl;
03107   int len;
03108   char buffer[MAXNAMLEN];
03109   utf8string utf8buffer;
03110   int who;
03111 
03112   /* Decode number of ACEs. */
03113   memcpy(&(acldata.naces), (char*)(Fattr->attr_vals.attrlist4_val + *LastOffset), sizeof(u_int));
03114   acldata.naces = ntohl(acldata.naces);
03115   LogFullDebug(COMPONENT_NFS_V4,
03116                "SATTR: Number of ACEs = %u",
03117                acldata.naces);
03118   *LastOffset += sizeof(u_int);
03119 
03120   /* Allocate memory for ACEs. */
03121   acldata.aces = (fsal_ace_t *)nfs4_ace_alloc(acldata.naces);
03122   if(acldata.aces == NULL)
03123     {
03124       LogCrit(COMPONENT_NFS_V4,
03125               "SATTR: Failed to allocate ACEs");
03126       return NFS4ERR_SERVERFAULT;
03127     }
03128   else
03129     memset(acldata.aces, 0, acldata.naces * sizeof(fsal_ace_t));
03130 
03131   /* Decode ACEs. */
03132   for(pace = acldata.aces; pace < acldata.aces + acldata.naces; pace++)
03133     {
03134       memcpy(&(pace->type), (char*)(Fattr->attr_vals.attrlist4_val + *LastOffset), sizeof(fsal_acetype_t));
03135       pace->type = ntohl(pace->type);
03136       LogFullDebug(COMPONENT_NFS_V4,
03137                    "SATTR: ACE type = 0x%x",
03138                    pace->type);
03139       *LastOffset += sizeof(fsal_acetype_t);
03140 
03141       memcpy(&(pace->flag), (char*)(Fattr->attr_vals.attrlist4_val + *LastOffset), sizeof(fsal_aceflag_t));
03142       pace->flag = ntohl(pace->flag);
03143       LogFullDebug(COMPONENT_NFS_V4,
03144                    "SATTR: ACE flag = 0x%x",
03145                    pace->flag);
03146       *LastOffset += sizeof(fsal_aceflag_t);
03147 
03148       memcpy(&(pace->perm), (char*)(Fattr->attr_vals.attrlist4_val + *LastOffset), sizeof(fsal_aceperm_t));
03149       pace->perm = ntohl(pace->perm);
03150       LogFullDebug(COMPONENT_NFS_V4,
03151                    "SATTR: ACE perm = 0x%x",
03152                    pace->perm);
03153       *LastOffset += sizeof(fsal_aceperm_t);
03154 
03155       /* Find out who type */
03156 
03157       /* Convert name to uid or gid */
03158       memcpy(&len, (char *)(Fattr->attr_vals.attrlist4_val + *LastOffset), sizeof(u_int));
03159       len = ntohl(len);        /* xdr marshalling on fattr4 */
03160       *LastOffset += sizeof(u_int);
03161 
03162       memcpy(buffer, (char *)(Fattr->attr_vals.attrlist4_val + *LastOffset), len);
03163       buffer[len] = '\0';
03164 
03165       /* Do not forget that xdr_opaque are aligned on 32bit long words */
03166       while((len % 4) != 0)
03167         len += 1;
03168 
03169       *LastOffset += len;
03170 
03171       /* Decode users. */
03172       LogFullDebug(COMPONENT_NFS_V4,
03173                    "SATTR: owner = %s, len = %d, type = %s",
03174                    buffer, len,
03175                    GET_FSAL_ACE_WHO_TYPE(*pace));
03176 
03177       utf8buffer.utf8string_val = buffer;
03178       utf8buffer.utf8string_len = strlen(buffer);
03179 
03180       if(nfs4_decode_acl_special_user(&utf8buffer, &who) == 0)  /* Decode special user. */
03181         {
03182           /* Clear group flag for special users */
03183           pace->flag &= ~(FSAL_ACE_FLAG_GROUP_ID);
03184           pace->iflag |= FSAL_ACE_IFLAG_SPECIAL_ID;
03185           pace->who.uid = who;
03186           LogFullDebug(COMPONENT_NFS_V4,
03187                        "SATTR: ACE special who.uid = 0x%x",
03188                        pace->who.uid);
03189         }
03190       else
03191         {
03192           if(pace->flag == FSAL_ACE_FLAG_GROUP_ID)  /* Decode group. */
03193             {
03194               utf82gid(&utf8buffer, &(pace->who.gid));
03195               LogFullDebug(COMPONENT_NFS_V4,
03196                            "SATTR: ACE who.gid = 0x%x",
03197                            pace->who.gid);
03198             }
03199           else  /* Decode user. */
03200             {
03201               utf82uid(&utf8buffer, &(pace->who.uid));
03202               LogFullDebug(COMPONENT_NFS_V4,
03203                            "SATTR: ACE who.uid = 0x%x",
03204                            pace->who.uid);
03205             }
03206         }
03207 
03208       /* Check if we can map a name string to uid or gid. If we can't, do cleanup
03209        * and bubble up NFS4ERR_BADOWNER. */
03210       if((pace->flag == FSAL_ACE_FLAG_GROUP_ID ? pace->who.gid : pace->who.uid) == -1)
03211         {
03212           LogFullDebug(COMPONENT_NFS_V4,
03213                        "SATTR: bad owner");
03214           nfs4_ace_free(acldata.aces);
03215           return NFS4ERR_BADOWNER;
03216         }
03217     }
03218 
03219   pacl = nfs4_acl_new_entry(&acldata, &status);
03220   pFSAL_attr->acl = pacl;
03221   if(pacl == NULL)
03222     {
03223       LogCrit(COMPONENT_NFS_V4,
03224               "SATTR: Failed to create a new entry for ACL");
03225       return NFS4ERR_SERVERFAULT;
03226     }
03227   else
03228      LogFullDebug(COMPONENT_NFS_V4,
03229                   "SATTR: Successfully created a new entry for ACL, status = %u",
03230                   status);
03231 
03232   /* Set new ACL */
03233   LogFullDebug(COMPONENT_NFS_V4,
03234                "SATTR: new acl = %p",
03235                pacl);
03236 
03237   return NFS4_OK;
03238 }
03239 #endif                          /* _USE_NFS4_ACL */
03240 
03254 int nfs4_attrmap_to_FSAL_attrmask(bitmap4 attrmap, fsal_attrib_mask_t* attrmask)
03255 {
03256   unsigned int offset = 0;
03257   unsigned int i = 0;
03258   char __attribute__ ((__unused__)) funcname[] = "nfs4_FattrToSattr";
03259 
03260   for(offset = 0; offset < attrmap.bitmap4_len; offset++)
03261     {
03262       for(i = 0; i < 32; i++)
03263         {
03264           if(attrmap.bitmap4_val[offset] & (1 << i)) {
03265             uint32_t val = i + 32 * offset;
03266             switch (val)
03267               {
03268               case FATTR4_TYPE:
03269                 *attrmask |= FSAL_ATTR_TYPE;
03270                 break;
03271               case FATTR4_FILEID:
03272                 *attrmask |= FSAL_ATTR_FILEID;
03273                 break;
03274               case FATTR4_FSID:
03275                 *attrmask |= FSAL_ATTR_FSID;
03276                 break;
03277               case FATTR4_NUMLINKS:
03278                 *attrmask |= FSAL_ATTR_NUMLINKS;
03279                 break;
03280               case FATTR4_SIZE:
03281                 *attrmask |= FSAL_ATTR_SIZE;
03282                 break;
03283               case FATTR4_MODE:
03284                 *attrmask |= FSAL_ATTR_MODE;
03285                 break;
03286               case FATTR4_OWNER:
03287                 *attrmask |= FSAL_ATTR_OWNER;
03288                 break;
03289               case FATTR4_OWNER_GROUP:
03290                 *attrmask |= FSAL_ATTR_GROUP;
03291                 break;
03292               case FATTR4_CHANGE:
03293                 *attrmask |= FSAL_ATTR_CHGTIME;
03294                 break;
03295               case FATTR4_RAWDEV:
03296                 *attrmask |= FSAL_ATTR_RAWDEV;
03297                 break;
03298               case FATTR4_SPACE_USED:
03299                 *attrmask |= FSAL_ATTR_SPACEUSED;
03300                 break;
03301               case FATTR4_TIME_ACCESS:
03302                 *attrmask |= FSAL_ATTR_ATIME;
03303                 break;
03304               case FATTR4_TIME_METADATA:
03305                 *attrmask |= FSAL_ATTR_CTIME;
03306                 break;
03307               case FATTR4_TIME_MODIFY:
03308                 *attrmask |= FSAL_ATTR_MTIME;
03309                 break;
03310               case FATTR4_TIME_ACCESS_SET:
03311                 *attrmask |= FSAL_ATTR_ATIME;
03312                 break;
03313               case FATTR4_TIME_MODIFY_SET:
03314                 *attrmask |= FSAL_ATTR_MTIME;
03315                 break;
03316               case FATTR4_FILEHANDLE:
03317                 LogFullDebug(COMPONENT_NFS_V4,
03318                              "Filehandle attribute requested on readdir!");
03319                 /* pFSAL_attr->asked_attributes |= FSAL_ATTR_FILEHANDLE; */
03320                 break;
03321 #ifdef _USE_NFS4_ACL
03322               case FATTR4_ACL:
03323                 *attrmask |= FSAL_ATTR_ACL;
03324                 break;
03325 #endif                          /* _USE_NFS4_ACL */
03326               }
03327           }
03328         }
03329     }
03330   return NFS4_OK;
03331 }                               /* nfs4_Fattr_To_FSAL_attr */
03332 
03333 static int nfstime4_to_fsal_time(fsal_time_t *ts, const char *attrval)
03334 {
03335   int LastOffset = 0;
03336   uint64_t seconds;
03337   uint32_t nseconds;
03338 
03339   memcpy(&seconds, attrval + LastOffset, sizeof(seconds));
03340   LastOffset += sizeof(seconds) ;
03341 
03342   memcpy(&nseconds, attrval + LastOffset, sizeof(nseconds));
03343   LastOffset += sizeof( nseconds ) ;
03344 
03345   ts->seconds = (uint32_t) nfs_ntohl64(seconds);
03346   ts->nseconds = (uint32_t) ntohl(nseconds);
03347 
03348   return LastOffset; 
03349 }
03350 
03351 static int settime4_to_fsal_time(fsal_time_t *ts, const char *attrval)
03352 {
03353   time_how4 how;
03354   int LastOffset = 0;
03355 
03356   memcpy(&how, attrval + LastOffset , sizeof(how));
03357   LastOffset += sizeof(how);
03358 
03359   if(ntohl(how) == SET_TO_SERVER_TIME4)
03360     {
03361       ts->seconds = time(NULL);   /* Use current server's time */
03362       ts->nseconds = 0;
03363     }
03364   else
03365     {
03366         LastOffset += nfstime4_to_fsal_time(ts, attrval + LastOffset);
03367     }
03368 
03369   return LastOffset;
03370 }
03371 
03389 int Fattr4_To_FSAL_attr(fsal_attrib_list_t * pFSAL_attr, fattr4 * Fattr, nfs_fh4 *hdl4)
03390 {
03391   u_int LastOffset = 0;
03392   unsigned int i = 0;
03393   uint32_t attrmasklist[FATTR4_MOUNTED_ON_FILEID];      /* List cannot be longer than FATTR4_MOUNTED_ON_FILEID */
03394   uint32_t attrmasklen = 0;
03395   uint32_t attribute_to_set = 0;
03396   int len;
03397   char buffer[MAXNAMLEN];
03398   utf8string utf8buffer;
03399 
03400   fattr4_type attr_type;
03401   fattr4_fsid attr_fsid;
03402   fattr4_fileid attr_fileid;
03403   fattr4_rdattr_error rdattr_error;
03404   fattr4_size attr_size;
03405   fattr4_change attr_change;
03406   fattr4_numlinks attr_numlinks;
03407   fattr4_rawdev attr_rawdev;
03408   fattr4_space_used attr_space_used;
03409 #ifdef _USE_NFS4_ACL
03410   int rc;
03411 #endif
03412 
03413   if(pFSAL_attr == NULL || Fattr == NULL)
03414     return NFS4ERR_BADXDR;
03415 
03416   /* Check attributes data */
03417   if((Fattr->attr_vals.attrlist4_val == NULL) ||
03418      (Fattr->attr_vals.attrlist4_len == 0))
03419     return NFS4_OK;
03420 
03421   /* Convert the attribute bitmap to an attribute list */
03422   nfs4_bitmap4_to_list(&(Fattr->attrmask), &attrmasklen, attrmasklist);
03423 
03424   LogFullDebug(COMPONENT_NFS_V4,
03425                "   nfs4_bitmap4_to_list ====> attrmasklen = %d", attrmasklen);
03426 
03427   /* Init */
03428   pFSAL_attr->asked_attributes = 0;
03429 
03430   for(i = 0; i < attrmasklen; i++)
03431     {
03432       attribute_to_set = attrmasklist[i];
03433 
03434 #ifdef _USE_NFS4_1
03435       if(attrmasklist[i] > FATTR4_FS_CHARSET_CAP)
03436 #else
03437       if(attrmasklist[i] > FATTR4_MOUNTED_ON_FILEID)
03438 #endif
03439         {
03440           /* Erroneous value... skip */
03441           continue;
03442         }
03443       LogFullDebug(COMPONENT_NFS_V4,
03444                    "=================> nfs4_Fattr_To_FSAL_attr: i=%u attr=%u", i,
03445                    attrmasklist[i]);
03446       LogFullDebug(COMPONENT_NFS_V4,
03447                    "Flag for Operation = %d|%d is ON,  name  = %s  reply_size = %d",
03448                    attrmasklist[i], fattr4tab[attribute_to_set].val,
03449                    fattr4tab[attribute_to_set].name,
03450                    fattr4tab[attribute_to_set].size_fattr4);
03451 
03452       switch (attribute_to_set)
03453         {
03454         case FATTR4_TYPE:
03455           memcpy((char *)&attr_type,
03456                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03457                  sizeof(fattr4_type));
03458 
03459           switch (ntohl(attr_type))
03460             {
03461             case NF4REG:
03462               pFSAL_attr->type = FSAL_TYPE_FILE;
03463               break;
03464 
03465             case NF4DIR:
03466               pFSAL_attr->type = FSAL_TYPE_DIR;
03467               break;
03468 
03469             case NF4BLK:
03470               pFSAL_attr->type = FSAL_TYPE_BLK;
03471               break;
03472 
03473             case NF4CHR:
03474               pFSAL_attr->type = FSAL_TYPE_CHR;
03475               break;
03476 
03477             case NF4LNK:
03478               pFSAL_attr->type = FSAL_TYPE_LNK;
03479               break;
03480 
03481             case NF4SOCK:
03482               pFSAL_attr->type = FSAL_TYPE_SOCK;
03483               break;
03484 
03485             case NF4FIFO:
03486               pFSAL_attr->type = FSAL_TYPE_FIFO;
03487               break;
03488 
03489             default:
03490               /* For wanting of a better solution */
03491               return NFS4ERR_BADXDR;
03492             }                   /* switch( pattr->type ) */
03493 
03494           pFSAL_attr->asked_attributes |= FSAL_ATTR_TYPE;
03495           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03496           break;
03497 
03498         case FATTR4_FILEID:
03499           /* The analog to the inode number. RFC3530 says "a number uniquely identifying the file within the filesystem"
03500            * I use hpss_GetObjId to extract this information from the Name Server's handle */
03501           memcpy((char *)&attr_fileid,
03502                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03503                  sizeof(fattr4_fileid));
03504           pFSAL_attr->fileid = nfs_ntohl64(attr_fileid);
03505 
03506           pFSAL_attr->asked_attributes |= FSAL_ATTR_FILEID;
03507           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03508 
03509           break;
03510 
03511         case FATTR4_FSID:
03512           memcpy((char *)&attr_fsid,
03513                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03514                  sizeof(fattr4_fsid));
03515           pFSAL_attr->fsid.major = nfs_ntohl64(attr_fsid.major);
03516           pFSAL_attr->fsid.minor = nfs_ntohl64(attr_fsid.minor);
03517 
03518           pFSAL_attr->asked_attributes |= FSAL_ATTR_FSID;
03519           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03520 
03521           break;
03522 
03523         case FATTR4_NUMLINKS:
03524           memcpy((char *)&attr_numlinks,
03525                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03526                  sizeof(fattr4_numlinks));
03527           pFSAL_attr->numlinks = ntohl(attr_numlinks);
03528 
03529           pFSAL_attr->asked_attributes |= FSAL_ATTR_NUMLINKS;
03530           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03531 
03532           break;
03533 
03534         case FATTR4_SIZE:
03535           memcpy((char *)&attr_size,
03536                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03537                  sizeof(fattr4_size));
03538 
03539           /* Do not forget the XDR marshalling for the fattr4 stuff */
03540           pFSAL_attr->filesize = nfs_ntohl64(attr_size);
03541 
03542           pFSAL_attr->asked_attributes |= FSAL_ATTR_SIZE;
03543           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03544           LogFullDebug(COMPONENT_NFS_V4,
03545                        "      SATTR: size seen %zu", (size_t)pFSAL_attr->filesize);
03546           break;
03547 
03548         case FATTR4_MODE:
03549           memcpy((char *)&(pFSAL_attr->mode),
03550                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03551                  sizeof(fattr4_mode));
03552 
03553           /* Do not forget the XDR marshalling for the fattr4 stuff */
03554           pFSAL_attr->mode = ntohl(pFSAL_attr->mode);
03555 
03556           pFSAL_attr->asked_attributes |= FSAL_ATTR_MODE;
03557           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03558           LogFullDebug(COMPONENT_NFS_V4,
03559                        "      SATTR: We see the mode 0%o", pFSAL_attr->mode);
03560           break;
03561 
03562         case FATTR4_OWNER:
03563           memcpy(&len, (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03564                  sizeof(u_int));
03565           len = ntohl(len);     /* xdr marshalling on fattr4 */
03566           LastOffset += sizeof(u_int);
03567 
03568           memcpy(buffer, (char *)(Fattr->attr_vals.attrlist4_val + LastOffset), len);
03569           buffer[len] = '\0';
03570 
03571           /* Do not forget that xdr_opaque are aligned on 32bit long words */
03572           while((len % 4) != 0)
03573             len += 1;
03574 
03575           LastOffset += len;
03576 
03577           utf8buffer.utf8string_val = buffer;
03578           utf8buffer.utf8string_len = strlen(buffer);
03579 
03580           utf82uid(&utf8buffer, &(pFSAL_attr->owner));
03581           pFSAL_attr->asked_attributes |= FSAL_ATTR_OWNER;
03582 
03583           LogFullDebug(COMPONENT_NFS_V4,
03584                        "      SATTR: We see the owner %s len = %d", buffer, len);
03585           LogFullDebug(COMPONENT_NFS_V4,
03586                        "      SATTR: We see the owner %d", pFSAL_attr->owner);
03587           break;
03588 
03589         case FATTR4_OWNER_GROUP:
03590           memcpy(&len, (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03591                  sizeof(u_int));
03592           len = ntohl(len);
03593           LastOffset += sizeof(u_int);
03594 
03595           memcpy(buffer, (char *)(Fattr->attr_vals.attrlist4_val + LastOffset), len);
03596           buffer[len] = '\0';
03597 
03598           /* Do not forget that xdr_opaque are aligned on 32bit long words */
03599           while((len % 4) != 0)
03600             len += 1;
03601 
03602           LastOffset += len;
03603 
03604           utf8buffer.utf8string_val = buffer;
03605           utf8buffer.utf8string_len = strlen(buffer);
03606 
03607           utf82gid(&utf8buffer, &(pFSAL_attr->group));
03608           pFSAL_attr->asked_attributes |= FSAL_ATTR_GROUP;
03609 
03610           LogFullDebug(COMPONENT_NFS_V4,
03611                        "      SATTR: We see the owner_group %s len = %d", buffer, len);
03612           LogFullDebug(COMPONENT_NFS_V4,
03613                        "      SATTR: We see the owner_group %d", pFSAL_attr->group);
03614           break;
03615 
03616         case FATTR4_CHANGE:
03617           memcpy((char *)&attr_change,
03618                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03619                  sizeof(fattr4_change));
03620           pFSAL_attr->chgtime.seconds = (uint32_t) nfs_ntohl64(attr_change);
03621           pFSAL_attr->chgtime.nseconds = 0;
03622 
03623           pFSAL_attr->change =  nfs_ntohl64(attr_change);
03624 
03625           pFSAL_attr->asked_attributes |= FSAL_ATTR_CHGTIME;
03626           pFSAL_attr->asked_attributes |= FSAL_ATTR_CHANGE;
03627           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03628 
03629           break;
03630 
03631         case FATTR4_RAWDEV:
03632           memcpy((char *)&attr_rawdev,
03633                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03634                  sizeof(fattr4_rawdev));
03635           pFSAL_attr->rawdev.major = (uint32_t) nfs_ntohl64(attr_rawdev.specdata1);
03636           pFSAL_attr->rawdev.minor = (uint32_t) nfs_ntohl64(attr_rawdev.specdata2);
03637 
03638           pFSAL_attr->asked_attributes |= FSAL_ATTR_RAWDEV;
03639           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03640 
03641           break;
03642 
03643         case FATTR4_SPACE_USED:
03644           memcpy((char *)&attr_space_used,
03645                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03646                  sizeof(fattr4_space_used));
03647           pFSAL_attr->spaceused = (uint32_t) nfs_ntohl64(attr_space_used);
03648 
03649           pFSAL_attr->asked_attributes |= FSAL_ATTR_SPACEUSED;
03650           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03651 
03652           break;
03653 
03654         case FATTR4_TIME_ACCESS:       /* Used only by FSAL_PROXY to reverse convert */
03655           LastOffset += nfstime4_to_fsal_time(&pFSAL_attr->atime, 
03656                                               (char *)(Fattr->attr_vals.attrlist4_val + LastOffset));
03657           pFSAL_attr->asked_attributes |= FSAL_ATTR_ATIME;
03658           break;
03659 
03660         case FATTR4_TIME_METADATA:     /* Used only by FSAL_PROXY to reverse convert */
03661           LastOffset += nfstime4_to_fsal_time(&pFSAL_attr->ctime, 
03662                                               (char *)(Fattr->attr_vals.attrlist4_val + LastOffset));
03663           pFSAL_attr->asked_attributes |= FSAL_ATTR_CTIME;
03664           break;
03665 
03666         case FATTR4_TIME_MODIFY:       /* Used only by FSAL_PROXY to reverse convert */
03667           LastOffset += nfstime4_to_fsal_time(&pFSAL_attr->mtime, 
03668                                               (char *)(Fattr->attr_vals.attrlist4_val + LastOffset));
03669           pFSAL_attr->asked_attributes |= FSAL_ATTR_MTIME;
03670           break;
03671 
03672         case FATTR4_TIME_ACCESS_SET:
03673           LastOffset += settime4_to_fsal_time(&pFSAL_attr->atime,
03674                                               Fattr->attr_vals.attrlist4_val + LastOffset);
03675           pFSAL_attr->asked_attributes |= FSAL_ATTR_ATIME;
03676           break;
03677 
03678         case FATTR4_TIME_MODIFY_SET:
03679           LastOffset += settime4_to_fsal_time(&pFSAL_attr->mtime,
03680                                               Fattr->attr_vals.attrlist4_val + LastOffset);
03681           pFSAL_attr->asked_attributes |= FSAL_ATTR_MTIME;
03682 
03683           break;
03684 
03685         case FATTR4_FILEHANDLE:
03686           memcpy(&len, (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03687                  sizeof(u_int));
03688           len = ntohl(len);
03689           LastOffset += sizeof(u_int);
03690           if(hdl4)
03691             {
03692                hdl4->nfs_fh4_len = len;
03693                hdl4->nfs_fh4_val = Fattr->attr_vals.attrlist4_val + LastOffset;
03694             }
03695           LastOffset += len;
03696           LogFullDebug(COMPONENT_NFS_V4,
03697                        "     SATTR: On a demande le filehandle len =%u", len);
03698           break;
03699 
03700         case FATTR4_RDATTR_ERROR:
03701           memcpy((char *)&rdattr_error,
03702                  (char *)(Fattr->attr_vals.attrlist4_val + LastOffset),
03703                  sizeof(fattr4_rdattr_error));
03704           rdattr_error = ntohl(rdattr_error);
03705           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03706 
03707           break;
03708 
03709 #ifdef _USE_NFS4_ACL
03710         case FATTR4_ACL:
03711           if((rc = nfs4_decode_acl(pFSAL_attr, Fattr, &LastOffset)) != NFS4_OK)
03712             return rc;
03713 
03714           pFSAL_attr->asked_attributes |= FSAL_ATTR_ACL;
03715           break;
03716 #endif                          /* _USE_NFS4_ACL */
03717 
03718         default:
03719           LogFullDebug(COMPONENT_NFS_V4,
03720                        "      SATTR: Attribut no supporte %d name=%s",
03721                        attribute_to_set, fattr4tab[attribute_to_set].name);
03722           LastOffset += fattr4tab[attribute_to_set].size_fattr4;
03723           /* return NFS4ERR_ATTRNOTSUPP ; *//* Should not stop processing */
03724           break;
03725         }                       /* switch */
03726     }                           /* for */
03727 
03728   return NFS4_OK;
03729 }                               /* Fattr4_To_FSAL_attr */
03730 
03743 int nfs4_Fattr_To_FSAL_attr(fsal_attrib_list_t * pFSAL_attr, fattr4 * Fattr)
03744 {
03745   return Fattr4_To_FSAL_attr(pFSAL_attr, Fattr, NULL);
03746 }
03747 
03748 /* Error conversion routines */
03760 nfsstat4 nfs4_Errno(cache_inode_status_t error)
03761 {
03762   nfsstat4 nfserror= NFS4ERR_INVAL;
03763 
03764   switch (error)
03765     {
03766     case CACHE_INODE_SUCCESS:
03767       nfserror = NFS4_OK;
03768       break;
03769 
03770     case CACHE_INODE_MALLOC_ERROR:
03771     case CACHE_INODE_POOL_MUTEX_INIT_ERROR:
03772     case CACHE_INODE_GET_NEW_LRU_ENTRY:
03773     case CACHE_INODE_INIT_ENTRY_FAILED:
03774     case CACHE_INODE_CACHE_CONTENT_EXISTS:
03775     case CACHE_INODE_CACHE_CONTENT_EMPTY:
03776       nfserror = NFS4ERR_SERVERFAULT;
03777       break;
03778 
03779     case CACHE_INODE_UNAPPROPRIATED_KEY:
03780       nfserror = NFS4ERR_BADHANDLE;
03781       break;
03782 
03783     case CACHE_INODE_BAD_TYPE:
03784     case CACHE_INODE_INVALID_ARGUMENT:
03785       nfserror = NFS4ERR_INVAL;
03786       break;
03787 
03788     case CACHE_INODE_NOT_A_DIRECTORY:
03789       nfserror = NFS4ERR_NOTDIR;
03790       break;
03791 
03792     case CACHE_INODE_ENTRY_EXISTS:
03793       nfserror = NFS4ERR_EXIST;
03794       break;
03795 
03796     case CACHE_INODE_DIR_NOT_EMPTY:
03797       nfserror = NFS4ERR_NOTEMPTY;
03798       break;
03799 
03800     case CACHE_INODE_NOT_FOUND:
03801       nfserror = NFS4ERR_NOENT;
03802       break;
03803 
03804     case CACHE_INODE_FSAL_ERROR:
03805     case CACHE_INODE_INSERT_ERROR:
03806     case CACHE_INODE_LRU_ERROR:
03807     case CACHE_INODE_HASH_SET_ERROR:
03808       nfserror = NFS4ERR_IO;
03809       break;
03810 
03811     case CACHE_INODE_FSAL_EACCESS:
03812       nfserror = NFS4ERR_ACCESS;
03813       break;
03814 
03815     case CACHE_INODE_FSAL_EPERM:
03816     case CACHE_INODE_FSAL_ERR_SEC:
03817       nfserror = NFS4ERR_PERM;
03818       break;
03819 
03820     case CACHE_INODE_NO_SPACE_LEFT:
03821       nfserror = NFS4ERR_NOSPC;
03822       break;
03823 
03824     case CACHE_INODE_IS_A_DIRECTORY:
03825       nfserror = NFS4ERR_ISDIR;
03826       break;
03827 
03828     case CACHE_INODE_READ_ONLY_FS:
03829       nfserror = NFS4ERR_ROFS;
03830       break;
03831 
03832     case CACHE_INODE_IO_ERROR:
03833       nfserror = NFS4ERR_IO;
03834       break;
03835 
03836      case CACHE_INODE_NAME_TOO_LONG:
03837       nfserror = NFS4ERR_NAMETOOLONG;
03838       break;
03839 
03840     case CACHE_INODE_KILLED:
03841     case CACHE_INODE_DEAD_ENTRY:
03842     case CACHE_INODE_FSAL_ESTALE:
03843       nfserror = NFS4ERR_STALE;
03844       break;
03845 
03846     case CACHE_INODE_STATE_CONFLICT:
03847       nfserror = NFS4ERR_PERM;
03848       break;
03849 
03850     case CACHE_INODE_QUOTA_EXCEEDED:
03851       nfserror = NFS4ERR_DQUOT;
03852       break;
03853 
03854     case CACHE_INODE_NOT_SUPPORTED:
03855       nfserror = NFS4ERR_NOTSUPP;
03856       break;
03857 
03858     case CACHE_INODE_DELAY:
03859       nfserror = NFS4ERR_DELAY;
03860       break;
03861 
03862     case CACHE_INODE_FILE_BIG:
03863       nfserror = NFS4ERR_FBIG;
03864       break;
03865 
03866     case CACHE_INODE_FILE_OPEN:
03867       nfserror = NFS4ERR_FILE_OPEN;
03868       break;
03869 
03870     case CACHE_INODE_STATE_ERROR:
03871       nfserror = NFS4ERR_BAD_STATEID;
03872       break;
03873 
03874     case CACHE_INODE_BAD_COOKIE:
03875       nfserror = NFS4ERR_BAD_COOKIE;
03876       break;
03877 
03878     case CACHE_INODE_INCONSISTENT_ENTRY:
03879     case CACHE_INODE_HASH_TABLE_ERROR:
03880     case CACHE_INODE_CACHE_CONTENT_ERROR:
03881     case CACHE_INODE_ASYNC_POST_ERROR:
03882       /* Should not occur */
03883       nfserror = NFS4ERR_INVAL;
03884       break;
03885     }
03886 
03887   return nfserror;
03888 }                               /* nfs4_Errno */
03889 
03901 nfsstat3 nfs3_Errno(cache_inode_status_t error)
03902 {
03903   nfsstat3 nfserror= NFS3ERR_INVAL;
03904 
03905   switch (error)
03906     {
03907     case CACHE_INODE_SUCCESS:
03908       nfserror = NFS3_OK;
03909       break;
03910 
03911     case CACHE_INODE_MALLOC_ERROR:
03912     case CACHE_INODE_POOL_MUTEX_INIT_ERROR:
03913     case CACHE_INODE_GET_NEW_LRU_ENTRY:
03914     case CACHE_INODE_UNAPPROPRIATED_KEY:
03915     case CACHE_INODE_INIT_ENTRY_FAILED:
03916     case CACHE_INODE_CACHE_CONTENT_EXISTS:
03917     case CACHE_INODE_CACHE_CONTENT_EMPTY:
03918     case CACHE_INODE_INSERT_ERROR:
03919     case CACHE_INODE_LRU_ERROR:
03920     case CACHE_INODE_HASH_SET_ERROR:
03921     case CACHE_INODE_FILE_OPEN:
03922       LogCrit(COMPONENT_NFSPROTO,
03923               "Error %u converted to NFS3ERR_IO but was set non-retryable",
03924               error);
03925       nfserror = NFS3ERR_IO;
03926       break;
03927 
03928     case CACHE_INODE_INVALID_ARGUMENT:
03929       nfserror = NFS3ERR_INVAL;
03930       break;
03931 
03932     case CACHE_INODE_FSAL_ERROR:
03933     case CACHE_INODE_CACHE_CONTENT_ERROR:
03935       LogCrit(COMPONENT_NFSPROTO,
03936               "Error CACHE_INODE_FSAL_ERROR converted to NFS3ERR_IO but was set non-retryable");
03937       nfserror = NFS3ERR_IO;
03938       break;
03939 
03940     case CACHE_INODE_NOT_A_DIRECTORY:
03941       nfserror = NFS3ERR_NOTDIR;
03942       break;
03943 
03944     case CACHE_INODE_ENTRY_EXISTS:
03945       nfserror = NFS3ERR_EXIST;
03946       break;
03947 
03948     case CACHE_INODE_DIR_NOT_EMPTY:
03949       nfserror = NFS3ERR_NOTEMPTY;
03950       break;
03951 
03952     case CACHE_INODE_NOT_FOUND:
03953       nfserror = NFS3ERR_NOENT;
03954       break;
03955 
03956     case CACHE_INODE_FSAL_EACCESS:
03957       nfserror = NFS3ERR_ACCES;
03958       break;
03959 
03960     case CACHE_INODE_FSAL_EPERM:
03961     case CACHE_INODE_FSAL_ERR_SEC:
03962       nfserror = NFS3ERR_PERM;
03963       break;
03964 
03965     case CACHE_INODE_NO_SPACE_LEFT:
03966       nfserror = NFS3ERR_NOSPC;
03967       break;
03968 
03969     case CACHE_INODE_IS_A_DIRECTORY:
03970       nfserror = NFS3ERR_ISDIR;
03971       break;
03972 
03973     case CACHE_INODE_READ_ONLY_FS:
03974       nfserror = NFS3ERR_ROFS;
03975       break;
03976 
03977     case CACHE_INODE_KILLED:
03978     case CACHE_INODE_DEAD_ENTRY:
03979     case CACHE_INODE_FSAL_ESTALE:
03980       nfserror = NFS3ERR_STALE;
03981       break;
03982 
03983     case CACHE_INODE_QUOTA_EXCEEDED:
03984       nfserror = NFS3ERR_DQUOT;
03985       break;
03986 
03987     case CACHE_INODE_BAD_TYPE:
03988       nfserror = NFS3ERR_BADTYPE;
03989       break;
03990 
03991     case CACHE_INODE_NOT_SUPPORTED:
03992       nfserror = NFS3ERR_NOTSUPP;
03993       break;
03994 
03995     case CACHE_INODE_DELAY:
03996       nfserror = NFS3ERR_JUKEBOX;
03997       break;
03998 
03999     case CACHE_INODE_IO_ERROR:
04000         LogCrit(COMPONENT_NFSPROTO,
04001                 "Error CACHE_INODE_IO_ERROR converted to NFS3ERR_IO but was set non-retryable");
04002       nfserror = NFS3ERR_IO;
04003       break;
04004 
04005     case CACHE_INODE_NAME_TOO_LONG:
04006       nfserror = NFS3ERR_NAMETOOLONG;
04007       break;
04008 
04009     case CACHE_INODE_FILE_BIG:
04010       nfserror = NFS3ERR_FBIG;
04011       break;
04012 
04013     case CACHE_INODE_BAD_COOKIE:
04014       nfserror = NFS3ERR_BAD_COOKIE;
04015       break;
04016 
04017     case CACHE_INODE_INCONSISTENT_ENTRY:
04018     case CACHE_INODE_HASH_TABLE_ERROR:
04019     case CACHE_INODE_STATE_CONFLICT:
04020     case CACHE_INODE_ASYNC_POST_ERROR:
04021     case CACHE_INODE_STATE_ERROR:
04022         /* Should not occur */
04023         LogDebug(COMPONENT_NFSPROTO,
04024                  "Line %u should never be reached in nfs3_Errno for cache_status=%u",
04025                  __LINE__, error);
04026       nfserror = NFS3ERR_INVAL;
04027       break;
04028     }
04029 
04030   return nfserror;
04031 }                               /* nfs3_Errno */
04032 
04044 nfsstat2 nfs2_Errno(cache_inode_status_t error)
04045 {
04046   nfsstat2 nfserror= NFSERR_IO;
04047 
04048   switch (error)
04049     {
04050     case CACHE_INODE_SUCCESS:
04051       nfserror = NFS_OK;
04052       break;
04053 
04054     case CACHE_INODE_MALLOC_ERROR:
04055     case CACHE_INODE_POOL_MUTEX_INIT_ERROR:
04056     case CACHE_INODE_GET_NEW_LRU_ENTRY:
04057     case CACHE_INODE_UNAPPROPRIATED_KEY:
04058     case CACHE_INODE_INIT_ENTRY_FAILED:
04059     case CACHE_INODE_BAD_TYPE:
04060     case CACHE_INODE_CACHE_CONTENT_EXISTS:
04061     case CACHE_INODE_CACHE_CONTENT_EMPTY:
04062     case CACHE_INODE_INSERT_ERROR:
04063     case CACHE_INODE_LRU_ERROR:
04064     case CACHE_INODE_HASH_SET_ERROR:
04065     case CACHE_INODE_INVALID_ARGUMENT:
04066     case CACHE_INODE_FILE_OPEN:
04067       LogCrit(COMPONENT_NFSPROTO,
04068               "Error %u converted to NFSERR_IO but was set non-retryable",
04069               error);
04070       nfserror = NFSERR_IO;
04071       break;
04072 
04073     case CACHE_INODE_NOT_A_DIRECTORY:
04074       nfserror = NFSERR_NOTDIR;
04075       break;
04076 
04077     case CACHE_INODE_ENTRY_EXISTS:
04078       nfserror = NFSERR_EXIST;
04079       break;
04080 
04081     case CACHE_INODE_FSAL_ERROR:
04082     case CACHE_INODE_CACHE_CONTENT_ERROR:
04083       LogCrit(COMPONENT_NFSPROTO,
04084               "Error CACHE_INODE_FSAL_ERROR converted to NFSERR_IO but was set non-retryable");
04085       nfserror = NFSERR_IO;
04086       break;
04087 
04088     case CACHE_INODE_DIR_NOT_EMPTY:
04089       nfserror = NFSERR_NOTEMPTY;
04090       break;
04091 
04092     case CACHE_INODE_NOT_FOUND:
04093       nfserror = NFSERR_NOENT;
04094       break;
04095 
04096     case CACHE_INODE_FSAL_EACCESS:
04097       nfserror = NFSERR_ACCES;
04098       break;
04099 
04100     case CACHE_INODE_NO_SPACE_LEFT:
04101       nfserror = NFSERR_NOSPC;
04102       break;
04103 
04104     case CACHE_INODE_FSAL_EPERM:
04105     case CACHE_INODE_FSAL_ERR_SEC:
04106       nfserror = NFSERR_PERM;
04107       break;
04108 
04109     case CACHE_INODE_IS_A_DIRECTORY:
04110       nfserror = NFSERR_ISDIR;
04111       break;
04112 
04113     case CACHE_INODE_READ_ONLY_FS:
04114       nfserror = NFSERR_ROFS;
04115       break;
04116 
04117     case CACHE_INODE_KILLED:
04118     case CACHE_INODE_DEAD_ENTRY:
04119     case CACHE_INODE_FSAL_ESTALE:
04120       nfserror = NFSERR_STALE;
04121       break;
04122 
04123     case CACHE_INODE_QUOTA_EXCEEDED:
04124       nfserror = NFSERR_DQUOT;
04125       break;
04126 
04127     case CACHE_INODE_IO_ERROR:
04128       LogCrit(COMPONENT_NFSPROTO,
04129               "Error CACHE_INODE_IO_ERROR converted to NFSERR_IO but was set non-retryable");
04130       nfserror = NFSERR_IO;
04131       break;
04132 
04133     case CACHE_INODE_NAME_TOO_LONG:
04134       nfserror = NFSERR_NAMETOOLONG;
04135       break;
04136 
04137     case CACHE_INODE_INCONSISTENT_ENTRY:
04138     case CACHE_INODE_HASH_TABLE_ERROR:
04139     case CACHE_INODE_STATE_CONFLICT:
04140     case CACHE_INODE_ASYNC_POST_ERROR:
04141     case CACHE_INODE_STATE_ERROR:
04142     case CACHE_INODE_NOT_SUPPORTED:
04143     case CACHE_INODE_DELAY:
04144     case CACHE_INODE_BAD_COOKIE:
04145     case CACHE_INODE_FILE_BIG:
04146         /* Should not occur */
04147       LogDebug(COMPONENT_NFSPROTO,
04148                "Line %u should never be reached in nfs2_Errno", __LINE__);
04149       nfserror = NFSERR_IO;
04150       break;
04151     }
04152 
04153   return nfserror;
04154 }                               /* nfs2_Errno */
04155 
04167 int nfs3_AllocateFH(nfs_fh3 *fh)
04168 {
04169   char __attribute__ ((__unused__)) funcname[] = "AllocateFH3";
04170 
04171   if(fh == NULL)
04172     return NFS3ERR_SERVERFAULT;
04173 
04174   /* Allocating the filehandle in memory */
04175   fh->data.data_len = sizeof(struct alloc_file_handle_v3);
04176   if((fh->data.data_val = gsh_malloc(fh->data.data_len)) == NULL)
04177     {
04178       LogError(COMPONENT_NFSPROTO, ERR_SYS, ERR_MALLOC, errno);
04179       return NFS3ERR_SERVERFAULT;
04180     }
04181 
04182   memset((char *)fh->data.data_val, 0, fh->data.data_len);
04183 
04184   return NFS3_OK;
04185 }                               /* nfs4_AllocateFH */
04186 
04198 int nfs4_AllocateFH(nfs_fh4 * fh)
04199 {
04200   char __attribute__ ((__unused__)) funcname[] = "AllocateFH4";
04201 
04202   if(fh == NULL)
04203     return NFS4ERR_SERVERFAULT;
04204 
04205   /* Allocating the filehandle in memory */
04206   fh->nfs_fh4_len = sizeof(struct alloc_file_handle_v4);
04207   if((fh->nfs_fh4_val = gsh_malloc(fh->nfs_fh4_len)) == NULL)
04208     {
04209       LogError(COMPONENT_NFS_V4, ERR_SYS, ERR_MALLOC, errno);
04210       return NFS4ERR_RESOURCE;
04211     }
04212 
04213   memset((char *)fh->nfs_fh4_val, 0, fh->nfs_fh4_len);
04214 
04215   return NFS4_OK;
04216 }                               /* nfs4_AllocateFH */
04217 
04229 int nfs4_MakeCred(compound_data_t * data)
04230 {
04231   exportlist_client_entry_t related_client;
04232   struct user_cred user_credentials;
04233 
04234   if (get_req_uid_gid(data->reqp,
04235                       data->pexport,
04236                       &user_credentials) == FALSE)
04237     return NFS4ERR_WRONGSEC;
04238 
04239   LogFullDebug(COMPONENT_DISPATCH,
04240                "nfs4_MakeCred about to call nfs_export_check_access");
04241   if(nfs_export_check_access(&data->pworker->hostaddr,
04242                              data->reqp,
04243                              data->pexport,
04244                              nfs_param.core_param.program[P_NFS],
04245                              nfs_param.core_param.program[P_MNT],
04246                              data->pworker->ht_ip_stats,
04247                              ip_stats_pool,
04248                              &related_client,
04249                              &user_credentials,
04250                              FALSE) /* So check_access() doesn't deny based on whether this is a RO export. */
04251      == FALSE)
04252     return NFS4ERR_WRONGSEC;
04253 
04254   if(nfs_check_anon(&related_client, data->pexport, &user_credentials) == FALSE
04255      || nfs_build_fsal_context(data->reqp,
04256                             data->pexport,
04257                             data->pcontext,
04258                             &user_credentials) == FALSE)
04259     return NFS4ERR_WRONGSEC;
04260 
04261   return NFS4_OK;
04262 }                               /* nfs4_MakeCred */
04263 
04264 /* Create access mask based on given access operation. Both mode and ace4
04265  * mask are encoded. */
04266 fsal_accessflags_t nfs_get_access_mask(uint32_t op, fsal_attrib_list_t *pattr)
04267 {
04268   fsal_accessflags_t access_mask = 0;
04269 
04270   switch(op)
04271     {
04272       case ACCESS3_READ:
04273         access_mask |= FSAL_MODE_MASK_SET(FSAL_R_OK);
04274         if(IS_FSAL_DIR(pattr->type))
04275           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR);
04276         else
04277           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_DATA);
04278       break;
04279 
04280       case ACCESS3_LOOKUP:
04281         if(!IS_FSAL_DIR(pattr->type))
04282           break;
04283         access_mask |= FSAL_MODE_MASK_SET(FSAL_X_OK);
04284         access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR);
04285       break;
04286 
04287       case ACCESS3_MODIFY:
04288         access_mask |= FSAL_MODE_MASK_SET(FSAL_W_OK);
04289         if(IS_FSAL_DIR(pattr->type))
04290           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_DELETE_CHILD);
04291         else
04292           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_DATA);
04293       break;
04294 
04295       case ACCESS3_EXTEND:
04296         access_mask |= FSAL_MODE_MASK_SET(FSAL_W_OK);
04297         if(IS_FSAL_DIR(pattr->type))
04298           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE |
04299                                             FSAL_ACE_PERM_ADD_SUBDIRECTORY);
04300         else
04301           access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_APPEND_DATA);
04302       break;
04303 
04304       case ACCESS3_DELETE:
04305         if(!IS_FSAL_DIR(pattr->type))
04306           break;
04307         access_mask |= FSAL_MODE_MASK_SET(FSAL_W_OK);
04308         access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_DELETE_CHILD);
04309       break;
04310 
04311       case ACCESS3_EXECUTE:
04312         if(IS_FSAL_DIR(pattr->type))
04313           break;
04314         access_mask |= FSAL_MODE_MASK_SET(FSAL_X_OK);
04315         access_mask |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_EXECUTE);
04316       break;
04317     }
04318 
04319   return access_mask;
04320 }
04321 
04322 void nfs3_access_debug(char *label, uint32_t access)
04323 {
04324   LogDebug(COMPONENT_NFSPROTO, "%s=%s,%s,%s,%s,%s,%s",
04325            label,
04326            FSAL_TEST_MASK(access, ACCESS3_READ) ? "READ" : "-",
04327            FSAL_TEST_MASK(access, ACCESS3_LOOKUP) ? "LOOKUP" : "-",
04328            FSAL_TEST_MASK(access, ACCESS3_MODIFY) ? "MODIFY" : "-",
04329            FSAL_TEST_MASK(access, ACCESS3_EXTEND) ? "EXTEND" : "-",
04330            FSAL_TEST_MASK(access, ACCESS3_DELETE) ? "DELETE" : "-",
04331            FSAL_TEST_MASK(access, ACCESS3_EXECUTE) ? "EXECUTE" : "-");
04332 }
04333 
04334 void nfs4_access_debug(char *label, uint32_t access, fsal_aceperm_t v4mask)
04335 {
04336   LogDebug(COMPONENT_NFSPROTO, "%s=%s,%s,%s,%s,%s,%s",
04337            label,
04338            FSAL_TEST_MASK(access, ACCESS3_READ) ? "READ" : "-",
04339            FSAL_TEST_MASK(access, ACCESS3_LOOKUP) ? "LOOKUP" : "-",
04340            FSAL_TEST_MASK(access, ACCESS3_MODIFY) ? "MODIFY" : "-",
04341            FSAL_TEST_MASK(access, ACCESS3_EXTEND) ? "EXTEND" : "-",
04342            FSAL_TEST_MASK(access, ACCESS3_DELETE) ? "DELETE" : "-",
04343            FSAL_TEST_MASK(access, ACCESS3_EXECUTE) ? "EXECUTE" : "-");
04344 
04345   if(v4mask)
04346     LogDebug(COMPONENT_NFSPROTO, "v4mask=%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
04347              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_READ_DATA)             ? 'r':'-',
04348              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_WRITE_DATA)            ? 'w':'-',
04349              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_EXECUTE)               ? 'x':'-',
04350              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_ADD_SUBDIRECTORY)    ? 'm':'-',
04351              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_READ_NAMED_ATTR)       ? 'n':'-',
04352              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_WRITE_NAMED_ATTR)      ? 'N':'-',
04353              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_DELETE_CHILD)          ? 'p':'-',
04354              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_READ_ATTR)             ? 't':'-',
04355              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_WRITE_ATTR)            ? 'T':'-',
04356              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_DELETE)                ? 'd':'-',
04357              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_READ_ACL)              ? 'c':'-',
04358              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_WRITE_ACL)             ? 'C':'-',
04359              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_WRITE_OWNER)   ? 'o':'-',
04360              FSAL_TEST_MASK(v4mask, FSAL_ACE_PERM_SYNCHRONIZE)   ? 'z':'-');
04361 }
04362 
04377 nfsstat4 nfs4_sanity_check_FH(compound_data_t *data,
04378                               cache_inode_file_type_t required_type)
04379 {
04380   /* If there is no FH */
04381   if(nfs4_Is_Fh_Empty(&(data->currentFH)))
04382     {
04383       LogDebug(COMPONENT_FILEHANDLE,
04384                "nfs4_Is_Fh_Empty failed");
04385       return NFS4ERR_NOFILEHANDLE;
04386     }
04387 
04388   /* If the filehandle is invalid */
04389   if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
04390     {
04391       LogDebug(COMPONENT_FILEHANDLE,
04392                "nfs4_Is_Fh_Invalid failed");
04393       return NFS4ERR_BADHANDLE;
04394     }
04395 
04396   /* Tests if the Filehandle is expired (for volatile filehandle) */
04397   if(nfs4_Is_Fh_Expired(&(data->currentFH)))
04398     {
04399       LogDebug(COMPONENT_FILEHANDLE,
04400                "nfs4_Is_Fh_Expired failed");
04401       return NFS4ERR_FHEXPIRED;
04402     }
04403 
04404   /* Check for the correct file type */
04405   if (required_type)
04406     {
04407       if(data->current_filetype != required_type)
04408         {
04409           LogDebug(COMPONENT_NFSPROTO,
04410                    "Wrong file type");
04411 
04412           if(required_type == DIRECTORY)
04413             return NFS4ERR_NOTDIR;
04414           if(required_type == SYMBOLIC_LINK)
04415             return NFS4ERR_INVAL;
04416 
04417           switch (data->current_filetype)
04418             {
04419             case DIRECTORY:
04420               return NFS4ERR_ISDIR;
04421             default:
04422               return NFS4ERR_INVAL;
04423             }
04424         }
04425     }
04426 
04427   return NFS4_OK;
04428 }
04429