int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { int i,length; struct inode *inode; char *link; #ifdef DEBUG printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname); #endif if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)) return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */ if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE) return -EINVAL; if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL) return -ENOMEM; if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) { kfree(link); return -EIO; } inode=dentry->d_inode; ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0; ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1; memcpy(link+8, symname, length+1); /* including last zero for io2vol */ /* map to/from server charset, do not touch upper/lower case as symlink can point out of ncp filesystem */ io2vol(NCP_SERVER(inode), link+8, 0); if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 0, length+8, link, &i) || i!=length+8) { kfree(link); return -EIO; } kfree(link); return 0; }
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct inode *inode; char *rawlink; int length, err, i, outlen; int kludge; int mode; __le32 attr; unsigned int hdr; DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname); if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) kludge = 0; else #ifdef CONFIG_NCPFS_EXTRAS if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS) kludge = 1; else #endif /* EPERM is returned by VFS if symlink procedure does not exist */ return -EPERM; rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); if (!rawlink) return -ENOMEM; if (kludge) { mode = 0; attr = aSHARED | aHIDDEN; ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0; ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1; hdr = 8; } else { mode = S_IFLNK | S_IRWXUGO; attr = 0; hdr = 0; } length = strlen(symname); /* map to/from server charset, do not touch upper/lower case as symlink can point out of ncp filesystem */ outlen = NCP_MAX_SYMLINK_SIZE - hdr; err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0); if (err) goto failfree; outlen += hdr; err = -EIO; if (ncp_create_new(dir,dentry,mode,0,attr)) { goto failfree; } inode=dentry->d_inode; if (ncp_make_open(inode, O_WRONLY)) goto failfree; if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 0, outlen, rawlink, &i) || i!=outlen) { goto fail; } ncp_inode_close(inode); ncp_make_closed(inode); kfree(rawlink); return 0; fail:; ncp_inode_close(inode); ncp_make_closed(inode); failfree:; kfree(rawlink); return err; }