nfs-ganesha 1.4

nfs4_op_lookup.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 "HashData.h"
00051 #include "HashTable.h"
00052 #include "log.h"
00053 #include "ganesha_rpc.h"
00054 #include "nfs23.h"
00055 #include "nfs4.h"
00056 #include "mount.h"
00057 #include "nfs_core.h"
00058 #include "cache_inode.h"
00059 #include "nfs_exports.h"
00060 #include "nfs_creds.h"
00061 #include "nfs_proto_functions.h"
00062 #include "nfs_tools.h"
00063 #include "nfs_proto_tools.h"
00064 
00077 #define arg_LOOKUP4 op->nfs_argop4_u.oplookup
00078 #define res_LOOKUP4 resp->nfs_resop4_u.oplookup
00079 
00080 int nfs4_op_lookup(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
00081 {
00082   char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookup";
00083 
00084   char strname[MAXNAMLEN];
00085 #ifndef _NO_XATTRD
00086   char objname[MAXNAMLEN];
00087 #endif
00088   fsal_name_t            name;
00089   unsigned int           xattr_found = FALSE;
00090   cache_entry_t        * dir_pentry = NULL;
00091   cache_entry_t        * file_pentry = NULL;
00092   fsal_attrib_list_t     attrlookup;
00093   cache_inode_status_t   cache_status;
00094   fsal_handle_t        * pfsal_handle = NULL;
00095 
00096   resp->resop = NFS4_OP_LOOKUP;
00097   res_LOOKUP4.status = NFS4_OK;
00098 
00099   /* Do basic checks on a filehandle */
00100   res_LOOKUP4.status = nfs4_sanity_check_FH(data, 0LL);
00101   if(res_LOOKUP4.status != NFS4_OK)
00102     return res_LOOKUP4.status;
00103 
00104   /* Check for empty name */
00105   if(op->nfs_argop4_u.oplookup.objname.utf8string_len == 0 ||
00106      op->nfs_argop4_u.oplookup.objname.utf8string_val == NULL)
00107     {
00108       res_LOOKUP4.status = NFS4ERR_INVAL;
00109       return res_LOOKUP4.status;
00110     }
00111 
00112   /* Check for name too long */
00113   if(op->nfs_argop4_u.oplookup.objname.utf8string_len > FSAL_MAX_NAME_LEN)
00114     {
00115       res_LOOKUP4.status = NFS4ERR_NAMETOOLONG;
00116       return res_LOOKUP4.status;
00117     }
00118 
00119   /* If Filehandle points to a pseudo fs entry, manage it via pseudofs specific functions */
00120   if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
00121     return nfs4_op_lookup_pseudo(op, data, resp);
00122 
00123   if (nfs_export_check_security(data->reqp, data->pexport) == FALSE)
00124     {
00125       res_LOOKUP4.status = NFS4ERR_PERM;
00126       return res_LOOKUP4.status;
00127     }
00128 
00129 #ifndef _NO_XATTRD
00130   /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
00131   if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
00132     return nfs4_op_lookup_xattr(op, data, resp);
00133 #endif
00134 
00135   /* UTF8 strings may not end with \0, but they carry their length */
00136   utf82str(strname, sizeof(strname), &arg_LOOKUP4.objname);
00137 
00138 #ifndef _NO_XATTRD
00139   /* Is this a .xattr.d.<object> name ? */
00140   if(nfs_XattrD_Name(strname, objname))
00141     {
00142       strcpy(strname, objname);
00143       xattr_found = TRUE;
00144     }
00145 #endif
00146 
00147   if((cache_status = cache_inode_error_convert(FSAL_str2name(strname,
00148                                                              MAXNAMLEN,
00149                                                              &name))) !=
00150      CACHE_INODE_SUCCESS)
00151     {
00152       res_LOOKUP4.status = nfs4_Errno(cache_status);
00153       return res_LOOKUP4.status;
00154     }
00155 
00156   /* No 'cd .' is allowed return NFS4ERR_BADNAME in this case */
00157   /* No 'cd .. is allowed, return EINVAL in this case. NFS4_OP_LOOKUPP should be use instead */
00158   if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
00159      || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
00160     {
00161       res_LOOKUP4.status = NFS4ERR_BADNAME;
00162       return res_LOOKUP4.status;
00163     }
00164 
00165   /* Do the lookup in the HPSS Namespace */
00166   file_pentry = NULL;
00167   dir_pentry = data->current_entry;
00168 
00169   /* Sanity check: dir_pentry should be ACTUALLY a directory */
00170   if(dir_pentry->type != DIRECTORY)
00171     {
00172       /* This is not a directory */
00173       if(dir_pentry->type == SYMBOLIC_LINK)
00174         res_LOOKUP4.status = NFS4ERR_SYMLINK;
00175       else
00176         res_LOOKUP4.status = NFS4ERR_NOTDIR;
00177 
00178       /* Return failed status */
00179       return res_LOOKUP4.status;
00180     }
00181 
00182   /* BUGAZOMEU: Faire la gestion des cross junction traverse */
00183   if((file_pentry = cache_inode_lookup(dir_pentry,
00184                                        &name,
00185                                        &attrlookup,
00186                                        data->pcontext, &cache_status)) != NULL)
00187     {
00188       /* Extract the fsal attributes from the cache inode pentry */
00189       pfsal_handle = &file_pentry->handle;
00190 
00191       /* Convert it to a file handle */
00192       if(!nfs4_FSALToFhandle(&data->currentFH, pfsal_handle, data))
00193         {
00194           res_LOOKUP4.status = NFS4ERR_SERVERFAULT;
00195           cache_inode_put(file_pentry);
00196           return res_LOOKUP4.status;
00197         }
00198 
00199       /* Copy this to the mounted on FH (if no junction is traversed */
00200       memcpy((char *)(data->mounted_on_FH.nfs_fh4_val),
00201              (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len);
00202       data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len;
00203 
00204 #if 0
00205       print_buff((char *)cache_inode_get_fsal_handle(file_pentry, &cache_status),
00206                  sizeof(fsal_handle_t));
00207       print_buff((char *)cache_inode_get_fsal_handle(dir_pentry, &cache_status),
00208                  sizeof(fsal_handle_t));
00209 #endif
00210       if(isFullDebug(COMPONENT_NFS_V4))
00211         {
00212           LogFullDebug(COMPONENT_NFS_V4,
00213                        "----> nfs4_op_lookup: name=%s  dir_pentry=%p  looked up pentry=%p",
00214                        strname, dir_pentry, file_pentry);
00215           LogFullDebug(COMPONENT_NFS_V4,
00216                        "----> FSAL handle parent and children in nfs4_op_lookup");
00217           print_buff(COMPONENT_NFS_V4,
00218                      (char *)&file_pentry->handle,
00219                      sizeof(fsal_handle_t));
00220           print_buff(COMPONENT_NFS_V4,
00221                      (char *)&dir_pentry->handle,
00222                      sizeof(fsal_handle_t));
00223         }
00224       LogHandleNFS4("NFS4 LOOKUP CURRENT FH: ", &data->currentFH);
00225 
00226       /* Release dir_pentry, as it is not reachable from anywhere in
00227          compound after this function returns.  Count on later
00228          operations or nfs4_Compound to clean up current_entry. */
00229 
00230       if (dir_pentry)
00231         cache_inode_put(dir_pentry);
00232 
00233       /* Keep the pointer within the compound data */
00234       data->current_entry = file_pentry;
00235       data->current_filetype = file_pentry->type;
00236 
00237       /* Return successfully */
00238       res_LOOKUP4.status = NFS4_OK;
00239 
00240 #ifndef _NO_XATTRD
00241       /* If this is a xattr ghost directory name, update the FH */
00242       if(xattr_found == TRUE)
00243         res_LOOKUP4.status = nfs4_fh_to_xattrfh(&(data->currentFH), &(data->currentFH));
00244 #endif
00245 
00246       if((data->current_entry->type == DIRECTORY) &&
00247          (data->current_entry->object.dir.referral != NULL))
00248         {
00249           if(!nfs4_Set_Fh_Referral(&(data->currentFH)))
00250             {
00251               res_LOOKUP4.status = NFS4ERR_SERVERFAULT;
00252               return res_LOOKUP4.status;
00253             }
00254         }
00255 
00256       return NFS4_OK;
00257 
00258     }
00259 
00260   /* If the part of the code is reached, then something wrong occured in the lookup process, status is not HPSS_E_NOERROR 
00261    * and contains the code for the error */
00262 
00263   res_LOOKUP4.status = nfs4_Errno(cache_status);
00264 
00265   return res_LOOKUP4.status;
00266 }                               /* nfs4_op_lookup */
00267 
00278 void nfs4_op_lookup_Free(LOOKUP4res * resp)
00279 {
00280   /* Nothing to be done */
00281   return;
00282 }                               /* nfs4_op_lookup_Free */