📄 dir.c
字号:
DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, (int) filp->f_pos); result = -EIO; if (!ncp_conn_valid(server)) goto out; result = 0; if (filp->f_pos == 0) { if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) goto out; filp->f_pos = 1; } if (filp->f_pos == 1) { if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR)) goto out; filp->f_pos = 2; } page = grab_cache_page(&inode->i_data, 0); if (!page) goto read_really; ctl.cache = cache = kmap(page); ctl.head = cache->head; if (!PageUptodate(page) || !ctl.head.eof) goto init_cache; if (filp->f_pos == 2) { if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) goto init_cache; mtime = ncp_obtain_mtime(dentry); mtime_valid = 1; if ((!mtime) || (mtime != ctl.head.mtime)) goto init_cache; } if (filp->f_pos > ctl.head.end) goto finished; ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2); ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; for (;;) { if (ctl.ofs != 0) { ctl.page = find_lock_page(&inode->i_data, ctl.ofs); if (!ctl.page) goto invalid_cache; ctl.cache = kmap(ctl.page); if (!PageUptodate(ctl.page)) goto invalid_cache; } while (ctl.idx < NCP_DIRCACHE_SIZE) { struct dentry *dent; int res; dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], dentry, filp->f_pos); if (!dent) goto invalid_cache; res = filldir(dirent, dent->d_name.name, dent->d_name.len, filp->f_pos, dent->d_inode->i_ino, DT_UNKNOWN); dput(dent); if (res) goto finished; filp->f_pos += 1; ctl.idx += 1; if (filp->f_pos > ctl.head.end) goto finished; } if (ctl.page) { kunmap(ctl.page); SetPageUptodate(ctl.page); unlock_page(ctl.page); page_cache_release(ctl.page); ctl.page = NULL; } ctl.idx = 0; ctl.ofs += 1; }invalid_cache: if (ctl.page) { kunmap(ctl.page); unlock_page(ctl.page); page_cache_release(ctl.page); ctl.page = NULL; } ctl.cache = cache;init_cache: ncp_invalidate_dircache_entries(dentry); if (!mtime_valid) { mtime = ncp_obtain_mtime(dentry); mtime_valid = 1; } ctl.head.mtime = mtime; ctl.head.time = jiffies; ctl.head.eof = 0; ctl.fpos = 2; ctl.ofs = 0; ctl.idx = NCP_DIRCACHE_START; ctl.filled = 0; ctl.valid = 1;read_really: if (ncp_is_server_root(inode)) { ncp_read_volume_list(filp, dirent, filldir, &ctl); } else { ncp_do_readdir(filp, dirent, filldir, &ctl); } ctl.head.end = ctl.fpos - 1; ctl.head.eof = ctl.valid;finished: if (page) { cache->head = ctl.head; kunmap(page); SetPageUptodate(page); unlock_page(page); page_cache_release(page); } if (ctl.page) { kunmap(ctl.page); SetPageUptodate(ctl.page); unlock_page(ctl.page); page_cache_release(ctl.page); }out: unlock_kernel(); return result;}static intncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctrl, struct ncp_entry_info *entry){ struct dentry *newdent, *dentry = filp->f_path.dentry; struct inode *newino, *inode = dentry->d_inode; struct ncp_cache_control ctl = *ctrl; struct qstr qname; int valid = 0; int hashed = 0; ino_t ino = 0; __u8 __name[NCP_MAXPATHLEN + 1]; qname.len = sizeof(__name); if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len, entry->i.entryName, entry->i.nameLen, !ncp_preserve_entry_case(inode, entry->i.NSCreator))) return 1; /* I'm not sure */ qname.name = __name; qname.hash = full_name_hash(qname.name, qname.len); if (dentry->d_op && dentry->d_op->d_hash) if (dentry->d_op->d_hash(dentry, &qname) != 0) goto end_advance; newdent = d_lookup(dentry, &qname); if (!newdent) { newdent = d_alloc(dentry, &qname); if (!newdent) goto end_advance; } else { hashed = 1; memcpy((char *) newdent->d_name.name, qname.name, newdent->d_name.len); } if (!newdent->d_inode) { entry->opened = 0; entry->ino = iunique(inode->i_sb, 2); newino = ncp_iget(inode->i_sb, entry); if (newino) { newdent->d_op = &ncp_dentry_operations; d_instantiate(newdent, newino); if (!hashed) d_rehash(newdent); } } else ncp_update_inode2(newdent->d_inode, entry); if (newdent->d_inode) { ino = newdent->d_inode->i_ino; newdent->d_fsdata = (void *) ctl.fpos; ncp_new_dentry(newdent); } if (ctl.idx >= NCP_DIRCACHE_SIZE) { if (ctl.page) { kunmap(ctl.page); SetPageUptodate(ctl.page); unlock_page(ctl.page); page_cache_release(ctl.page); } ctl.cache = NULL; ctl.idx -= NCP_DIRCACHE_SIZE; ctl.ofs += 1; ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); if (ctl.page) ctl.cache = kmap(ctl.page); } if (ctl.cache) { ctl.cache->dentry[ctl.idx] = newdent; valid = 1; } dput(newdent);end_advance: if (!valid) ctl.valid = 0; if (!ctl.filled && (ctl.fpos == filp->f_pos)) { if (!ino) ino = find_inode_number(dentry, &qname); if (!ino) ino = iunique(inode->i_sb, 2); ctl.filled = filldir(dirent, qname.name, qname.len, filp->f_pos, ino, DT_UNKNOWN); if (!ctl.filled) filp->f_pos += 1; } ctl.fpos += 1; ctl.idx += 1; *ctrl = ctl; return (ctl.valid || !ctl.filled);}static voidncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctl){ struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct ncp_server *server = NCP_SERVER(inode); struct ncp_volume_info info; struct ncp_entry_info entry; int i; DPRINTK("ncp_read_volume_list: pos=%ld\n", (unsigned long) filp->f_pos); for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { if (ncp_get_volume_info_with_number(server, i, &info) != 0) return; if (!strlen(info.volume_name)) continue; DPRINTK("ncp_read_volume_list: found vol: %s\n", info.volume_name); if (ncp_lookup_volume(server, info.volume_name, &entry.i)) { DPRINTK("ncpfs: could not lookup vol %s\n", info.volume_name); continue; } entry.volume = entry.i.volNumber; if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) return; }}static voidncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, struct ncp_cache_control *ctl){ struct dentry *dentry = filp->f_path.dentry; struct inode *dir = dentry->d_inode; struct ncp_server *server = NCP_SERVER(dir); struct nw_search_sequence seq; struct ncp_entry_info entry; int err; void* buf; int more; size_t bufsize; DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n", dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) filp->f_pos); PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n", dentry->d_name.name, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); err = ncp_initialize_search(server, dir, &seq); if (err) { DPRINTK("ncp_do_readdir: init failed, err=%d\n", err); return; } /* We MUST NOT use server->buffer_size handshaked with server if we are using UDP, as for UDP server uses max. buffer size determined by MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). So we use 128KB, just to be sure, as there is no way how to know this value in advance. */ bufsize = 131072; buf = vmalloc(bufsize); if (!buf) return; do { int cnt; char* rpl; size_t rpls; err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); if (err) /* Error */ break; if (!cnt) /* prevent endless loop */ break; while (cnt--) { size_t onerpl; if (rpls < offsetof(struct nw_info_struct, entryName)) break; /* short packet */ ncp_extract_file_info(rpl, &entry.i); onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; if (rpls < onerpl) break; /* short packet */ (void)ncp_obtain_nfs_info(server, &entry.i); rpl += onerpl; rpls -= onerpl; entry.volume = entry.i.volNumber; if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) break; } } while (more); vfree(buf); return;}int ncp_conn_logged_in(struct super_block *sb){ struct ncp_server* server = NCP_SBP(sb); int result; if (ncp_single_volume(server)) { int len; struct dentry* dent; __u32 volNumber; __le32 dirEntNum; __le32 DosDirNum; __u8 __name[NCP_MAXPATHLEN + 1]; len = sizeof(__name); result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, strlen(server->m.mounted_vol), 1); if (result) goto out; result = -ENOENT; if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { PPRINTK("ncp_conn_logged_in: %s not found\n", server->m.mounted_vol); goto out; } dent = sb->s_root; if (dent) { struct inode* ino = dent->d_inode; if (ino) { NCP_FINFO(ino)->volNumber = volNumber; NCP_FINFO(ino)->dirEntNum = dirEntNum; NCP_FINFO(ino)->DosDirNum = DosDirNum; } else { DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); } } else { DPRINTK("ncpfs: sb->s_root == NULL!\n"); } } result = 0;out: return result;}static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ struct ncp_server *server = NCP_SERVER(dir); struct inode *inode = NULL; struct ncp_entry_info finfo; int error, res, len; __u8 __name[NCP_MAXPATHLEN + 1]; lock_kernel(); error = -EIO; if (!ncp_conn_valid(server)) goto finished; PPRINTK("ncp_lookup: server lookup for %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); len = sizeof(__name); if (ncp_is_server_root(dir)) { res = ncp_io2vol(server, __name, &len, dentry->d_name.name, dentry->d_name.len, 1); if (!res) res = ncp_lookup_volume(server, __name, &(finfo.i)); } else { res = ncp_io2vol(server, __name, &len, dentry->d_name.name, dentry->d_name.len, !ncp_preserve_case(dir)); if (!res) res = ncp_obtain_info(server, dir, __name, &(finfo.i)); } PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n", dentry->d_parent->d_name.name, __name, res); /* * If we didn't find an entry, make a negative dentry. */ if (res) goto add_entry; /* * Create an inode for the entry. */ finfo.opened = 0; finfo.ino = iunique(dir->i_sb, 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -