📄 inode.c
字号:
error = -ENOTSOCK; sock_inode = server->info_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput2; info_sock = SOCKET_I(sock_inode); if (!info_sock) goto out_fput2; error = -EBADFD; if (info_sock->type != SOCK_STREAM) goto out_fput2; server->info_sock = info_sock; }/* server->lock = 0; */ mutex_init(&server->mutex); server->packet = NULL;/* server->buffer_size = 0; *//* server->conn_status = 0; *//* server->root_dentry = NULL; *//* server->root_setuped = 0; */#ifdef CONFIG_NCPFS_PACKET_SIGNING/* server->sign_wanted = 0; *//* server->sign_active = 0; */#endif server->auth.auth_type = NCP_AUTH_NONE;/* server->auth.object_name_len = 0; *//* server->auth.object_name = NULL; *//* server->auth.object_type = 0; *//* server->priv.len = 0; *//* server->priv.data = NULL; */ server->m = data; /* Althought anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 1) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.time_out = server->m.time_out * HZ / 100; server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;#ifdef CONFIG_NCPFS_NLS /* load the default NLS charsets */ server->nls_vol = load_nls_default(); server->nls_io = load_nls_default();#endif /* CONFIG_NCPFS_NLS */ server->dentry_ttl = 0; /* no caching */ INIT_LIST_HEAD(&server->tx.requests); mutex_init(&server->rcv.creq_mutex); server->tx.creq = NULL; server->rcv.creq = NULL; server->data_ready = sock->sk->sk_data_ready; server->write_space = sock->sk->sk_write_space; server->error_report = sock->sk->sk_error_report; sock->sk->sk_user_data = server; init_timer(&server->timeout_tm);#undef NCP_PACKET_SIZE#define NCP_PACKET_SIZE 131072 error = -ENOMEM; server->packet_size = NCP_PACKET_SIZE; server->packet = vmalloc(NCP_PACKET_SIZE); if (server->packet == NULL) goto out_nls; server->txbuf = vmalloc(NCP_PACKET_SIZE); if (server->txbuf == NULL) goto out_packet; server->rxbuf = vmalloc(NCP_PACKET_SIZE); if (server->rxbuf == NULL) goto out_txbuf; sock->sk->sk_data_ready = ncp_tcp_data_ready; sock->sk->sk_error_report = ncp_tcp_error_report; if (sock->type == SOCK_STREAM) { server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_rxbuf; DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */#ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, default_bufsize, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, default_bufsize, options & 2, &(server->buffer_size), &options) != 0) { goto out_disconnect; } } if (options & 2) server->sign_wanted = 1; } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, default_bufsize, &(server->buffer_size)) != 0) goto out_disconnect; DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); memset(&finfo, 0, sizeof(finfo)); finfo.i.attributes = aDIR; finfo.i.dataStreamSize = 0; /* ignored */ finfo.i.dirEntNum = 0; finfo.i.DosDirNum = 0;#ifdef CONFIG_NCPFS_SMALLDOS finfo.i.NSCreator = NW_NS_DOS;#endif finfo.volume = NCP_NUMBER_OF_VOLUMES; /* set dates of mountpoint to Jan 1, 1986; 00:00 */ finfo.i.creationTime = finfo.i.modifyTime = cpu_to_le16(0x0000); finfo.i.creationDate = finfo.i.modifyDate = finfo.i.lastAccessDate = cpu_to_le16(0x0C21); finfo.i.nameLen = 0; finfo.i.entryName[0] = '\0'; finfo.opened = 0; finfo.ino = 2; /* tradition */ server->name_space[finfo.volume] = NW_NS_DOS; error = -ENOMEM; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_disconnect; DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) goto out_no_root; sb->s_root->d_op = &ncp_root_dentry_operations; return 0;out_no_root: iput(root_inode);out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server);out_rxbuf: ncp_stop_tasks(server); vfree(server->rxbuf);out_txbuf: vfree(server->txbuf);out_packet: vfree(server->packet);out_nls:#ifdef CONFIG_NCPFS_NLS unload_nls(server->nls_io); unload_nls(server->nls_vol);#endifout_fput2: if (server->info_filp) fput(server->info_filp);out_fput: /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: * * The previously used put_filp(ncp_filp); was bogous, since * it doesn't proper unlocking. */ fput(ncp_filp);out: put_pid(data.wdog_pid); sb->s_fs_info = NULL; kfree(server); return error;}static void ncp_put_super(struct super_block *sb){ struct ncp_server *server = NCP_SBP(sb); ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); ncp_stop_tasks(server);#ifdef CONFIG_NCPFS_NLS /* unload the NLS charsets */ if (server->nls_vol) { unload_nls(server->nls_vol); server->nls_vol = NULL; } if (server->nls_io) { unload_nls(server->nls_io); server->nls_io = NULL; }#endif /* CONFIG_NCPFS_NLS */ if (server->info_filp) fput(server->info_filp); fput(server->ncp_filp); kill_pid(server->m.wdog_pid, SIGTERM, 1); put_pid(server->m.wdog_pid); kfree(server->priv.data); kfree(server->auth.object_name); vfree(server->rxbuf); vfree(server->txbuf); vfree(server->packet); sb->s_fs_info = NULL; kfree(server);}static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf){ struct dentry* d; struct inode* i; struct ncp_inode_info* ni; struct ncp_server* s; struct ncp_volume_info vi; struct super_block *sb = dentry->d_sb; int err; __u8 dh; d = sb->s_root; if (!d) { goto dflt; } i = d->d_inode; if (!i) { goto dflt; } ni = NCP_FINFO(i); if (!ni) { goto dflt; } s = NCP_SBP(sb); if (!s) { goto dflt; } if (!s->m.mounted_vol[0]) { goto dflt; } err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); if (err) { goto dflt; } err = ncp_get_directory_info(s, dh, &vi); ncp_dirhandle_free(s, dh); if (err) { goto dflt; } buf->f_type = NCP_SUPER_MAGIC; buf->f_bsize = vi.sectors_per_block * 512; buf->f_blocks = vi.total_blocks; buf->f_bfree = vi.free_blocks; buf->f_bavail = vi.free_blocks; buf->f_files = vi.total_dir_entries; buf->f_ffree = vi.available_dir_entries; buf->f_namelen = 12; return 0; /* We cannot say how much disk space is left on a mounted NetWare Server, because free space is distributed over volumes, and the current user might have disk quotas. So free space is not that simple to determine. Our decision here is to err conservatively. */dflt:; buf->f_type = NCP_SUPER_MAGIC; buf->f_bsize = NCP_BLOCK_SIZE; buf->f_blocks = 0; buf->f_bfree = 0; buf->f_bavail = 0; buf->f_namelen = 12; return 0;}int ncp_notify_change(struct dentry *dentry, struct iattr *attr){ struct inode *inode = dentry->d_inode; int result = 0; __le32 info_mask; struct nw_modify_dos_info info; struct ncp_server *server; result = -EIO; lock_kernel(); server = NCP_SERVER(inode); if ((!server) || !ncp_conn_valid(server)) goto out; /* ageing the dentry to force validation */ ncp_age_dentry(server, dentry); result = inode_change_ok(inode, attr); if (result < 0) goto out; result = -EPERM; if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->m.uid))) goto out; if (((attr->ia_valid & ATTR_GID) && (attr->ia_gid != server->m.gid))) goto out; if (((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) goto out; info_mask = 0; memset(&info, 0, sizeof(info));#if 1 if ((attr->ia_valid & ATTR_MODE) != 0) { umode_t newmode = attr->ia_mode; info_mask |= DM_ATTRIBUTES; if (S_ISDIR(inode->i_mode)) { newmode &= server->m.dir_mode; } else {#ifdef CONFIG_NCPFS_EXTRAS if (server->m.flags & NCP_MOUNT_EXTRAS) { /* any non-default execute bit set */ if (newmode & ~server->m.file_mode & S_IXUGO) info.attributes |= aSHARED | aSYSTEM; /* read for group/world and not in default file_mode */ else if (newmode & ~server->m.file_mode & S_IRUGO) info.attributes |= aSHARED; } else#endif newmode &= server->m.file_mode; } if (newmode & S_IWUGO) info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); else info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);#ifdef CONFIG_NCPFS_NFS_NS if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { result = ncp_modify_nfs_info(server, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum, attr->ia_mode, 0); if (result != 0) goto out; info.attributes &= ~(aSHARED | aSYSTEM); { /* mark partial success */ struct iattr tmpattr; tmpattr.ia_valid = ATTR_MODE; tmpattr.ia_mode = attr->ia_mode; result = inode_setattr(inode, &tmpattr); if (result) goto out; } }#endif }#endif /* Do SIZE before attributes, otherwise mtime together with size does not work... */ if ((attr->ia_valid & ATTR_SIZE) != 0) { int written; DPRINTK("ncpfs: trying to change size to %ld\n", attr->ia_size); if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { result = -EACCES; goto out; } ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, attr->ia_size, 0, "", &written); /* According to ndir, the changes only take effect after closing the file */ ncp_inode_close(inode); result = ncp_make_closed(inode); if (result) goto out; { struct iattr tmpattr; tmpattr.ia_valid = ATTR_SIZE; tmpattr.ia_size = attr->ia_size; result = inode_setattr(inode, &tmpattr); if (result) goto out; } } if ((attr->ia_valid & ATTR_CTIME) != 0) { info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); ncp_date_unix2dos(attr->ia_ctime.tv_sec, &info.creationTime, &info.creationDate); } if ((attr->ia_valid & ATTR_MTIME) != 0) { info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); ncp_date_unix2dos(attr->ia_mtime.tv_sec, &info.modifyTime, &info.modifyDate); } if ((attr->ia_valid & ATTR_ATIME) != 0) { __le16 dummy; info_mask |= (DM_LAST_ACCESS_DATE); ncp_date_unix2dos(attr->ia_atime.tv_sec, &dummy, &info.lastAccessDate); } if (info_mask != 0) { result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), inode, info_mask, &info); if (result != 0) { result = -EACCES; if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { /* NetWare seems not to allow this. I do not know why. So, just tell the user everything went fine. This is a terrible hack, but I do not know how to do this correctly. */ result = 0; } else goto out; }#ifdef CONFIG_NCPFS_STRONG if ((!result) && (info_mask & DM_ATTRIBUTES)) NCP_FINFO(inode)->nwattr = info.attributes;#endif } if (!result) result = inode_setattr(inode, attr);out: unlock_kernel(); return result;}static int ncp_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt){ return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);}static struct file_system_type ncp_fs_type = { .owner = THIS_MODULE, .name = "ncpfs", .get_sb = ncp_get_sb, .kill_sb = kill_anon_super,};static int __init init_ncp_fs(void){ int err; DPRINTK("ncpfs: init_module called\n"); err = init_inodecache(); if (err) goto out1; err = register_filesystem(&ncp_fs_type); if (err) goto out; return 0;out: destroy_inodecache();out1: return err;}static void __exit exit_ncp_fs(void){ DPRINTK("ncpfs: cleanup_module called\n"); unregister_filesystem(&ncp_fs_type); destroy_inodecache();}module_init(init_ncp_fs)module_exit(exit_ncp_fs)MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -