int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) { int rc = -EOPNOTSUPP; unsigned int xid; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; char *full_path = NULL; struct inode *newinode = NULL; xid = get_xid(); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) { rc = PTR_ERR(tlink); goto symlink_exit; } pTcon = tlink_tcon(tlink); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; goto symlink_exit; } cifs_dbg(FYI, "Full path: %s\n", full_path); cifs_dbg(FYI, "symname is %s\n", symname); /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); /* else rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, cifs_sb_target->local_nls); */ if (rc == 0) { if (pTcon->unix_ext) rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, xid); else rc = cifs_get_inode_info(&newinode, full_path, NULL, inode->i_sb, xid, NULL); if (rc != 0) { cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n", rc); } else { d_instantiate(direntry, newinode); } } symlink_exit: kfree(full_path); cifs_put_tlink(tlink); free_xid(xid); return rc; }
int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) { int rc = -EOPNOTSUPP; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; FreeXid(xid); return rc; } cFYI(1, "Full path: %s", full_path); cFYI(1, "symname is %s", symname); /* BB what if DFS and this volume is on different share? BB */ if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); /* else rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, cifs_sb_target->local_nls); */ if (rc == 0) { if (pTcon->unix_ext) rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, xid); else rc = cifs_get_inode_info(&newinode, full_path, NULL, inode->i_sb, xid, NULL); if (rc != 0) { cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", rc); } else { if (pTcon->nocase) direntry->d_op = &cifs_ci_dentry_ops; else direntry->d_op = &cifs_dentry_ops; d_instantiate(direntry, newinode); } } kfree(full_path); FreeXid(xid); return rc; }
int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) { int rc = -EOPNOTSUPP; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; down(&inode->i_sb->s_vfs_rename_sem); full_path = build_path_from_dentry(direntry); up(&inode->i_sb->s_vfs_rename_sem); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; } cFYI(1, ("Full path: %s ", full_path)); cFYI(1, ("symname is %s", symname)); /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); /* else rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */ if (rc == 0) { if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb); else rc = cifs_get_inode_info(&newinode, full_path, NULL, inode->i_sb); if (rc != 0) { cFYI(1, ("Create symlink worked but get_inode_info failed with rc = %d ", rc)); } else { direntry->d_op = &cifs_dentry_ops; d_instantiate(direntry, newinode); } } if (full_path) kfree(full_path); FreeXid(xid); return rc; }