inode.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,013 行 · 第 1/2 页
C
1,013 行
sock_inode = server->info_filp->f_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; */ init_MUTEX(&server->sem); 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); init_MUTEX(&server->rcv.creq_sem); 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; 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, server); INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server); sock->sk->sk_write_space = ncp_tcp_write_space; } else { INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server); INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server); 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_packet; 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_packet: ncp_stop_tasks(server); 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: 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_proc(server->m.wdog_pid, SIGTERM, 1); if (server->priv.data) ncp_kfree_s(server->priv.data, server->priv.len); if (server->auth.object_name) ncp_kfree_s(server->auth.object_name, server->auth.object_name_len); vfree(server->packet); sb->s_fs_info = NULL; kfree(server);}static int ncp_statfs(struct super_block *sb, struct kstatfs *buf){ struct dentry* d; struct inode* i; struct ncp_inode_info* ni; struct ncp_server* s; struct ncp_volume_info vi; 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;}#ifdef DEBUG_NCP_MALLOCint ncp_malloced;int ncp_current_malloced;#endifstatic struct super_block *ncp_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data){ return get_sb_nodev(fs_type, flags, data, ncp_fill_super);}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");#ifdef DEBUG_NCP_MALLOC ncp_malloced = 0; ncp_current_malloced = 0;#endif 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();#ifdef DEBUG_NCP_MALLOC PRINTK("ncp_malloced: %d\n", ncp_malloced); PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);#endif}module_init(init_ncp_fs)module_exit(exit_ncp_fs)MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?