int fsal_internal_proxy_fsal_utf8_2_name(fsal_name_t * pname, utf8string * utf8str) { char tmpstr[FSAL_MAX_NAME_LEN]; fsal_status_t fsal_status; if(pname == NULL || utf8str == NULL) return FALSE; if(utf82str(tmpstr, sizeof(tmpstr), utf8str) == -1) return FALSE; fsal_status = FSAL_str2name(tmpstr, FSAL_MAX_NAME_LEN, pname); if(fsal_status.major != ERR_FSAL_NO_ERROR) return FALSE; return TRUE; } /* fsal_internal_proxy_fsal_utf8_2_name */
int fsal_internal_proxy_fsal_utf8_2_path(fsal_path_t * ppath, utf8string * utf8str) { char tmpstr[FSAL_MAX_PATH_LEN]; fsal_status_t fsal_status; if(ppath == NULL || utf8str == NULL) return FALSE; if(utf82str(tmpstr, sizeof(tmpstr), utf8str) == -1) return FALSE; fsal_status = FSAL_str2path(tmpstr, FSAL_MAX_PATH_LEN, ppath); if(fsal_status.major != ERR_FSAL_NO_ERROR) return FALSE; return TRUE; } /* fsal_internal_proxy_fsal_utf8_2_path */
/** * * utf82gid: converts a utf8 string descriptorto a gid . * * Converts a utf8 string descriptor to a gid . * * @param utf8str [IN] group's name as UTF8 string. * @param Gid [OUT] pointer to the computed gid. * * @return 0 in all cases */ int utf82gid(utf8string * utf8str, gid_t * Gid) { char buff[2 * NFS4_MAX_DOMAIN_LEN]; char gidname[NFS4_MAX_DOMAIN_LEN]; #ifndef _USE_NFSIDMAP char domainname[NFS4_MAX_DOMAIN_LEN]; #endif int rc; if(utf8str->utf8string_len == 0) { *Gid = -1; /* Nobody */ LogCrit(COMPONENT_IDMAPPER, "utf82gid: empty group name"); return 0; } utf82str(buff, sizeof(buff), utf8str); #ifndef _USE_NFSIDMAP /* Group is shown as a string 'group@domain' , remove it if libnfsidmap is not used */ nfs4_stringid_split(buff, gidname, domainname); #else strncpy(gidname, buff, NFS4_MAX_DOMAIN_LEN); #endif rc = name2gid(gidname, Gid); if(rc == 0) { *Gid = -1; /* Nobody */ return 0; } LogDebug(COMPONENT_IDMAPPER, "utf82gid: Mapped %s to gid = %d", buff, *Gid); return 0; } /* utf82gid */
int nfs4_op_lookup(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { fsal_name_t name; char strname[MAXNAMLEN]; #ifndef _NO_XATTRD char objname[MAXNAMLEN]; #endif unsigned int xattr_found = FALSE; cache_entry_t *dir_pentry = NULL; cache_entry_t *file_pentry = NULL; fsal_attrib_list_t attrlookup; cache_inode_status_t cache_status; fsal_handle_t *pfsal_handle = NULL; char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookup"; resp->resop = NFS4_OP_LOOKUP; res_LOOKUP4.status = NFS4_OK; /* If there is no FH */ if(nfs4_Is_Fh_Empty(&(data->currentFH))) { res_LOOKUP4.status = NFS4ERR_NOFILEHANDLE; return res_LOOKUP4.status; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->currentFH))) { res_LOOKUP4.status = NFS4ERR_BADHANDLE; return res_LOOKUP4.status; } /* Tests if the Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->currentFH))) { res_LOOKUP4.status = NFS4ERR_FHEXPIRED; return res_LOOKUP4.status; } /* Check for empty name */ if(op->nfs_argop4_u.oplookup.objname.utf8string_len == 0 || op->nfs_argop4_u.oplookup.objname.utf8string_val == NULL) { res_LOOKUP4.status = NFS4ERR_INVAL; return res_LOOKUP4.status; } /* Check for name to long */ if(op->nfs_argop4_u.oplookup.objname.utf8string_len > FSAL_MAX_NAME_LEN) { res_LOOKUP4.status = NFS4ERR_NAMETOOLONG; return res_LOOKUP4.status; } /* If Filehandle points to a pseudo fs entry, manage it via pseudofs specific functions */ if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) return nfs4_op_lookup_pseudo(op, data, resp); #ifndef _NO_XATTRD /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */ if(nfs4_Is_Fh_Xattr(&(data->currentFH))) return nfs4_op_lookup_xattr(op, data, resp); #endif /* UTF8 strings may not end with \0, but they carry their length */ utf82str(strname, sizeof(strname), &arg_LOOKUP4.objname); #ifndef _NO_XATTRD /* Is this a .xattr.d.<object> name ? */ if(nfs_XattrD_Name(strname, objname)) { strcpy(strname, objname); xattr_found = TRUE; } #endif if((cache_status = cache_inode_error_convert(FSAL_str2name(strname, MAXNAMLEN, &name))) != CACHE_INODE_SUCCESS) { res_LOOKUP4.status = nfs4_Errno(cache_status); return res_LOOKUP4.status; } /* No 'cd .' is allowed return NFS4ERR_BADNAME in this case */ /* No 'cd .. is allowed, return EINVAL in this case. NFS4_OP_LOOKUPP should be use instead */ if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT) || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT)) { res_LOOKUP4.status = NFS4ERR_BADNAME; return res_LOOKUP4.status; } /* Do the lookup in the HPSS Namespace */ file_pentry = NULL; dir_pentry = data->current_entry; /* Sanity check: dir_pentry should be ACTUALLY a directory */ if(dir_pentry->internal_md.type != DIR_BEGINNING && dir_pentry->internal_md.type != DIR_CONTINUE) { /* This is not a directory */ if(dir_pentry->internal_md.type == SYMBOLIC_LINK) res_LOOKUP4.status = NFS4ERR_SYMLINK; else res_LOOKUP4.status = NFS4ERR_NOTDIR; /* Return failed status */ return res_LOOKUP4.status; } /* BUGAZOMEU: Faire la gestion des cross junction traverse */ if((file_pentry = cache_inode_lookup(dir_pentry, &name, &attrlookup, data->ht, data->pclient, data->pcontext, &cache_status)) != NULL) { /* Extract the fsal attributes from the cache inode pentry */ pfsal_handle = cache_inode_get_fsal_handle(file_pentry, &cache_status); if(cache_status != CACHE_INODE_SUCCESS) { res_LOOKUP4.status = NFS4ERR_SERVERFAULT; return res_LOOKUP4.status; } /* Convert it to a file handle */ if(!nfs4_FSALToFhandle(&data->currentFH, pfsal_handle, data)) { res_LOOKUP4.status = NFS4ERR_SERVERFAULT; return res_LOOKUP4.status; } /* Copy this to the mounted on FH (if no junction is traversed */ memcpy((char *)(data->mounted_on_FH.nfs_fh4_val), (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len); data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len; #if 0 print_buff((char *)cache_inode_get_fsal_handle(file_pentry, &cache_status), sizeof(fsal_handle_t)); print_buff((char *)cache_inode_get_fsal_handle(dir_pentry, &cache_status), sizeof(fsal_handle_t)); #endif if(isFullDebug(COMPONENT_NFS_V4)) { LogFullDebug(COMPONENT_NFS_V4, "----> nfs4_op_lookup: name=%s dir_pentry=%p looked up pentry=%p", strname, dir_pentry, file_pentry); LogFullDebug(COMPONENT_NFS_V4, "----> FSAL handle parent puis fils dans nfs4_op_lookup"); print_buff(COMPONENT_NFS_V4, (char *)cache_inode_get_fsal_handle(file_pentry, &cache_status), sizeof(fsal_handle_t)); print_buff(COMPONENT_NFS_V4, (char *)cache_inode_get_fsal_handle(dir_pentry, &cache_status), sizeof(fsal_handle_t)); } LogHandleNFS4("NFS4 LOOKUP CURRENT FH: ", &data->currentFH); /* Keep the pointer within the compound data */ data->current_entry = file_pentry; data->current_filetype = file_pentry->internal_md.type; /* Return successfully */ res_LOOKUP4.status = NFS4_OK; #ifndef _NO_XATTRD /* If this is a xattr ghost directory name, update the FH */ if(xattr_found == TRUE) res_LOOKUP4.status = nfs4_fh_to_xattrfh(&(data->currentFH), &(data->currentFH)); #endif if((data->current_entry->internal_md.type == DIR_BEGINNING) && (data->current_entry->object.dir_begin.referral != NULL)) { if(!nfs4_Set_Fh_Referral(&(data->currentFH))) { res_LOOKUP4.status = NFS4ERR_SERVERFAULT; return res_LOOKUP4.status; } } return NFS4_OK; } /* If the part of the code is reached, then something wrong occured in the lookup process, status is not HPSS_E_NOERROR * and contains the code for the error */ res_LOOKUP4.status = nfs4_Errno(cache_status); return res_LOOKUP4.status; } /* nfs4_op_lookup */
int nfs4_op_create(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { cache_entry_t *pentry_parent = NULL; cache_entry_t *pentry_new = NULL; fsal_attrib_list_t attr_parent; fsal_attrib_list_t attr_new; fsal_attrib_list_t sattr; fsal_handle_t *pnewfsal_handle = NULL; nfs_fh4 newfh4; cache_inode_status_t cache_status; int convrc = 0; fsal_accessmode_t mode = 0600; fsal_name_t name; cache_inode_create_arg_t create_arg; char __attribute__ ((__unused__)) funcname[] = "nfs4_op_create"; unsigned int i = 0; resp->resop = NFS4_OP_CREATE; res_CREATE4.status = NFS4_OK; /* If the filehandle is Empty */ if(nfs4_Is_Fh_Empty(&(data->currentFH))) { res_CREATE4.status = NFS4ERR_NOFILEHANDLE; return res_CREATE4.status; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->currentFH))) { res_CREATE4.status = NFS4ERR_BADHANDLE; return res_CREATE4.status; } /* Tests if the Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->currentFH))) { res_CREATE4.status = NFS4ERR_FHEXPIRED; return res_CREATE4.status; } /* Pseudo Fs is explictely a Read-Only File system */ if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) { res_CREATE4.status = NFS4ERR_ROFS; return res_CREATE4.status; } /* Ask only for supported attributes */ if(!nfs4_Fattr_Supported(&arg_CREATE4.createattrs)) { res_CREATE4.status = NFS4ERR_ATTRNOTSUPP; return res_CREATE4.status; } /* Do not use READ attr, use WRITE attr */ if(!nfs4_Fattr_Check_Access(&arg_CREATE4.createattrs, FATTR4_ATTR_WRITE)) { res_CREATE4.status = NFS4ERR_INVAL; return res_CREATE4.status; } /* Check for name to long */ if(arg_CREATE4.objname.utf8string_len > FSAL_MAX_NAME_LEN) { res_CREATE4.status = NFS4ERR_NAMETOOLONG; return res_CREATE4.status; } /* * This operation is used to create a non-regular file, * this means: - a symbolic link * - a block device file * - a character device file * - a socket file * - a fifo * - a directory * * You can't use this operation to create a regular file, you have to use NFS4_OP_OPEN for this */ /* Convert the UFT8 objname to a regular string */ if(arg_CREATE4.objname.utf8string_len == 0) { res_CREATE4.status = NFS4ERR_INVAL; return res_CREATE4.status; } if(utf82str(name.name, &arg_CREATE4.objname) == -1) { res_CREATE4.status = NFS4ERR_INVAL; return res_CREATE4.status; } name.len = strlen(name.name); /* Sanuty check: never create a directory named '.' or '..' */ if(arg_CREATE4.objtype.type == NF4DIR) { if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT) || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT)) { res_CREATE4.status = NFS4ERR_BADNAME; return res_CREATE4.status; } } /* Filename should contain not slash */ for(i = 0; i < name.len; i++) { if(name.name[i] == '/') { res_CREATE4.status = NFS4ERR_BADCHAR; return res_CREATE4.status; } } /* Convert current FH into a cached entry, the current_pentry (assocated with the current FH will be used for this */ pentry_parent = data->current_entry; /* The currentFH must point to a directory (objects are always created within a directory) */ if(data->current_filetype != DIR_BEGINNING && data->current_filetype != DIR_CONTINUE) { res_CREATE4.status = NFS4ERR_NOTDIR; return res_CREATE4.status; } /* get attributes of parent directory, for 'change4' info replyed */ if((cache_status = cache_inode_getattr(pentry_parent, &attr_parent, data->ht, data->pclient, data->pcontext, &cache_status)) != CACHE_INODE_SUCCESS) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* Change info for client cache coherency, pentry internal_md is used for that */ memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.before), 0, sizeof(changeid4)); res_CREATE4.CREATE4res_u.resok4.cinfo.before = (changeid4) pentry_parent->internal_md.mod_time; /* Convert the incoming fattr4 to a vattr structure, if such arguments are supplied */ if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0) { /* Arguments were supplied, extract them */ convrc = nfs4_Fattr_To_FSAL_attr(&sattr, &(arg_CREATE4.createattrs)); if(convrc == 0) { res_CREATE4.status = NFS4ERR_ATTRNOTSUPP; return res_CREATE4.status; } if(convrc == -1) { res_CREATE4.status = NFS4ERR_BADXDR; return res_CREATE4.status; } } /* Create either a symbolic link or a directory */ switch (arg_CREATE4.objtype.type) { case NF4LNK: /* Convert the name to link from into a regular string */ if(arg_CREATE4.objtype.createtype4_u.linkdata.utf8string_len == 0) { res_CREATE4.status = NFS4ERR_INVAL; return res_CREATE4.status; } else { if(utf82str (create_arg.link_content.path, &arg_CREATE4.objtype.createtype4_u.linkdata) == -1) { res_CREATE4.status = NFS4ERR_INVAL; return res_CREATE4.status; } create_arg.link_content.len = strlen(create_arg.link_content.path); } /* do the symlink operation */ if((pentry_new = cache_inode_create(pentry_parent, &name, SYMBOLIC_LINK, mode, &create_arg, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; case NF4DIR: /* Create a new directory */ /* do the symlink operation */ if((pentry_new = cache_inode_create(pentry_parent, &name, DIR_BEGINNING, mode, &create_arg, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; case NF4SOCK: /* Create a new socket file */ if((pentry_new = cache_inode_create(pentry_parent, &name, SOCKET_FILE, mode, NULL, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; case NF4FIFO: /* Create a new socket file */ if((pentry_new = cache_inode_create(pentry_parent, &name, FIFO_FILE, mode, NULL, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; case NF4CHR: create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1; create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2; /* Create a new socket file */ if((pentry_new = cache_inode_create(pentry_parent, &name, CHARACTER_FILE, mode, &create_arg, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; case NF4BLK: create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1; create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2; /* Create a new socket file */ if((pentry_new = cache_inode_create(pentry_parent, &name, BLOCK_FILE, mode, &create_arg, &attr_new, data->ht, data->pclient, data->pcontext, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* If entry exists pentry_new is not null but cache_status was set */ if(cache_status == CACHE_INODE_ENTRY_EXISTS) { res_CREATE4.status = NFS4ERR_EXIST; return res_CREATE4.status; } break; default: /* Should never happen, but return NFS4ERR_BADTYPE in this case */ res_CREATE4.status = NFS4ERR_BADTYPE; return res_CREATE4.status; break; } /* switch( arg_CREATE4.objtype.type ) */ /* Now produce the filehandle to this file */ if((pnewfsal_handle = cache_inode_get_fsal_handle(pentry_new, &cache_status)) == NULL) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* Allocation of a new file handle */ if(nfs4_AllocateFH(&newfh4) != NFS4_OK) { res_CREATE4.status = NFS4ERR_SERVERFAULT; return res_CREATE4.status; } /* Building the new file handle */ if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data)) { res_CREATE4.status = NFS4ERR_SERVERFAULT; return res_CREATE4.status; } /* This new fh replaces the current FH */ data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len; memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len); /* No do not need newfh any more */ Mem_Free((char *)newfh4.nfs_fh4_val); /* Set the mode if requested */ /* Use the same fattr mask for reply, if one attribute was not settable, NFS4ERR_ATTRNOTSUPP was replyied */ res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len = arg_CREATE4.createattrs.attrmask.bitmap4_len; if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0) { if((cache_status = cache_inode_setattr(pentry_new, &sattr, data->ht, data->pclient, data->pcontext, &cache_status)) != CACHE_INODE_SUCCESS) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } /* Allocate a new bitmap */ res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val = (unsigned int *)Mem_Alloc(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len * sizeof(u_int)); if(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val == NULL) { res_CREATE4.status = NFS4ERR_SERVERFAULT; return res_CREATE4.status; } memset(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val, 0, res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len); memcpy(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val, arg_CREATE4.createattrs.attrmask.bitmap4_val, res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len * sizeof(u_int)); } /* Get the change info on parent directory after the operation was successfull */ if((cache_status = cache_inode_getattr(pentry_parent, &attr_parent, data->ht, data->pclient, data->pcontext, &cache_status)) != CACHE_INODE_SUCCESS) { res_CREATE4.status = nfs4_Errno(cache_status); return res_CREATE4.status; } memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.after), 0, sizeof(changeid4)); res_CREATE4.CREATE4res_u.resok4.cinfo.after = (changeid4) pentry_parent->internal_md.mod_time; /* Operation is supposed to be atomic .... */ res_CREATE4.CREATE4res_u.resok4.cinfo.atomic = TRUE; LogFullDebug(COMPONENT_NFS_V4, " CREATE CINFO before = %llu after = %llu atomic = %d\n", res_CREATE4.CREATE4res_u.resok4.cinfo.before, res_CREATE4.CREATE4res_u.resok4.cinfo.after, res_CREATE4.CREATE4res_u.resok4.cinfo.atomic); /* @todo : BUGAZOMEU: fair ele free dans cette fonction */ /* Keep the vnode entry for the file in the compound data */ data->current_entry = pentry_new; data->current_filetype = pentry_new->internal_md.type; /* If you reach this point, then no error occured */ res_CREATE4.status = NFS4_OK; return res_CREATE4.status; } /* nfs4_op_create */