static void ncp_evict_inode(struct inode *inode) { truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); if (S_ISDIR(inode->i_mode)) { DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino); } if (ncp_make_closed(inode) != 0) { /* We can't do anything but complain. */ printk(KERN_ERR "ncp_evict_inode: could not close\n"); } }
/* * Fill in the inode based on the ncp_entry_info structure. */ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) { struct ncp_server *server = NCP_SERVER(inode); NCP_FINFO(inode)->flags = 0; ncp_update_attrs(inode, nwinfo); DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); inode->i_nlink = 1; inode->i_uid = server->m.uid; inode->i_gid = server->m.gid; ncp_update_dates(inode, &nwinfo->i); ncp_update_inode(inode, nwinfo); }
static int ncp_do_request(struct ncp_server *server, int size, void* reply, int max_reply_size) { int result; if (server->lock == 0) { printk(KERN_ERR "ncpfs: Server not locked!\n"); return -EIO; } if (!ncp_conn_valid(server)) { printk(KERN_ERR "ncpfs: Connection invalid!\n"); return -EIO; } { sigset_t old_set; unsigned long mask, flags; spin_lock_irqsave(¤t->sighand->siglock, flags); old_set = current->blocked; if (current->flags & PF_EXITING) mask = 0; else mask = sigmask(SIGKILL); if (server->m.flags & NCP_MOUNT_INTR) { if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGINT); if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGQUIT); } siginitsetinv(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); result = do_ncp_rpc_call(server, size, reply, max_reply_size); spin_lock_irqsave(¤t->sighand->siglock, flags); current->blocked = old_set; recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); } DDPRINTK("do_ncp_rpc_call returned %d\n", result); return result; }
/* * Fill in the inode based on the nw_file_info structure. */ static void ncp_set_attr(struct inode *inode, struct nw_file_info *nwinfo) { struct nw_info_struct *nwi = &nwinfo->i; struct ncp_server *server = NCP_SERVER(inode); if (nwi->attributes & aDIR) { inode->i_mode = server->m.dir_mode; /* for directories dataStreamSize seems to be some Object ID ??? */ inode->i_size = 512; } else { inode->i_mode = server->m.file_mode; inode->i_size = le32_to_cpu(nwi->dataStreamSize); } if (nwi->attributes & aRONLY) inode->i_mode &= ~0222; DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); inode->i_nlink = 1; inode->i_uid = server->m.uid; inode->i_gid = server->m.gid; inode->i_blksize = 512; inode->i_rdev = 0; inode->i_blocks = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) { inode->i_blocks = (inode->i_size - 1) / inode->i_blksize + 1; } inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime), le16_to_cpu(nwi->modifyDate)); inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime), le16_to_cpu(nwi->creationDate)); inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate)); ncp_update_inode(inode, nwinfo); }
static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) { poll_table wait_table; struct file *file; struct socket *sock; int init_timeout; size_t dataread; int result = 0; file = server->ncp_filp; sock = &file->f_dentry->d_inode->u.socket_i; dataread = 0; init_timeout = server->m.time_out * 20; /* hard-mounted volumes have no timeout, except connection close... */ if (!(server->m.flags & NCP_MOUNT_SOFT)) init_timeout = 0x7FFF0000; while (len) { poll_initwait(&wait_table); /* mb() is not necessary because ->poll() will serialize instructions adding the wait_table waitqueues in the waitqueue-head before going to calculate the mask-retval. */ __set_current_state(TASK_INTERRUPTIBLE); if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) { init_timeout = schedule_timeout(init_timeout); poll_freewait(&wait_table); current->state = TASK_RUNNING; if (signal_pending(current)) { return -ERESTARTSYS; } if (!init_timeout) { return -EIO; } if(wait_table.error) { return wait_table.error; } } else { poll_freewait(&wait_table); } current->state = TASK_RUNNING; result = _recv(sock, buffer, len, MSG_DONTWAIT); if (result < 0) { if (result == -EAGAIN) { DDPRINTK("ncpfs: tcp: bad select ready\n"); continue; } return result; } if (result == 0) { printk(KERN_ERR "ncpfs: tcp: EOF on socket\n"); return -EIO; } if (result > len) { printk(KERN_ERR "ncpfs: tcp: bug in recvmsg\n"); return -EIO; } dataread += result; buffer += result; len -= result; } return 0; }
static int smb_lookup(struct inode *dir, const char *name, int len, struct inode **result) { struct smb_dirent finfo; struct smb_inode_info *result_info; int error; int found_in_cache; struct smb_inode_info *new_inode_info = NULL; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("smb_lookup: inode is NULL or not a directory.\n"); iput(dir); return -ENOENT; } DDPRINTK("smb_lookup: %s\n", name); /* Fast cheat for . */ if (len == 0 || (len == 1 && name[0] == '.')) { *result = dir; return 0; } /* ..and for .. */ if (len == 2 && name[0] == '.' && name[1] == '.') { struct smb_inode_info *parent = SMB_INOP(dir)->dir; if (parent->state == SMB_INODE_CACHED) { parent->state = SMB_INODE_LOOKED_UP; } *result = iget(dir->i_sb, smb_info_ino(parent)); iput(dir); if (*result == 0) { return -EACCES; } return 0; } result_info = smb_find_dir_inode(dir, name, len); in_tree: if (result_info != NULL) { if (result_info->state == SMB_INODE_CACHED) { result_info->state = SMB_INODE_LOOKED_UP; } *result = iget(dir->i_sb, smb_info_ino(result_info)); iput(dir); if (new_inode_info != NULL) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); } if (*result == NULL) { return -EACCES; } return 0; } /* If the file is in the dir cache, we do not have to ask the server. */ found_in_cache = 0; if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0)) { int first = c_last_returned_index; int i; i = first; do { if (compare_filename(SMB_SERVER(dir), name, len, &(c_entry[i])) == 0) { finfo = c_entry[i]; found_in_cache = 1; break; } i = (i + 1) % c_size; } while (i != first); } if (found_in_cache == 0) { DPRINTK("smb_lookup: not found in cache: %s\n", name); if (len > SMB_MAXNAMELEN) { iput(dir); return -ENAMETOOLONG; } error = smb_proc_getattr(dir, name, len, &finfo); if (error < 0) { iput(dir); return error; } finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); } new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), GFP_KERNEL); /* Here somebody else might have inserted the inode */ result_info = smb_find_dir_inode(dir, name, len); if (result_info != NULL) { goto in_tree; } if (new_inode_info == NULL) { iput(dir); return -ENOMEM; } new_inode_info->finfo = finfo; DPRINTK("attr: %x\n", finfo.attr); if ((*result = smb_iget(dir, new_inode_info)) == NULL) { iput(dir); return -EACCES; } DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info); iput(dir); return 0; }
static int smb_readdir(struct inode *dir, struct file *filp, void *dirent, filldir_t filldir) { int result, i = 0; struct smb_dirent *entry = NULL; struct smb_server *server = SMB_SERVER(dir); DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos); DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n", dir->i_ino, c_ino); if ((dir == NULL) || !S_ISDIR(dir->i_mode)) { printk("smb_readdir: dir is NULL or not a directory\n"); return -EBADF; } if (c_entry == NULL) { i = sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE; c_entry = (struct smb_dirent *) smb_vmalloc(i); if (c_entry == NULL) { printk("smb_readdir: no MEMORY for cache\n"); return -ENOMEM; } } if (filp->f_pos == 0) { c_ino = 0; c_dev = 0; c_seen_eof = 0; if (filldir(dirent, ".", 1, filp->f_pos, smb_info_ino(SMB_INOP(dir))) < 0) { return 0; } filp->f_pos += 1; } if (filp->f_pos == 1) { if (filldir(dirent, "..", 2, filp->f_pos, smb_info_ino(SMB_INOP(dir)->dir)) < 0) { return 0; } filp->f_pos += 1; } entry = smb_search_in_cache(dir, filp->f_pos); if (entry == NULL) { if (c_seen_eof) { /* End of directory */ return 0; } result = smb_refill_dir_cache(server, dir, filp->f_pos); if (result <= 0) { return result; } entry = c_entry; } while (entry < &(c_entry[c_size])) { /* We found it. For getwd(), we have to return the correct inode in d_ino if the inode is currently in use. Otherwise the inode number does not matter. (You can argue a lot about this..) */ struct smb_inode_info *ino_info = smb_find_dir_inode(dir, entry->name, entry->len); ino_t ino = entry->f_ino; if (ino_info != NULL) { ino = smb_info_ino(ino_info); } DDPRINTK("smb_readdir: entry->name = %s\n", entry->name); DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos); if (filldir(dirent, entry->name, strlen(entry->name), entry->f_pos, ino) < 0) { break; } if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino) || (entry->f_pos != filp->f_pos)) { /* Someone has destroyed the cache while we slept in filldir */ break; } filp->f_pos += 1; entry += 1; } return 0; }
static void smb_read_inode(struct inode *inode) { /* Our task should be extremely simple here. We only have to look up the information somebody else (smb_iget) put into the inode tree. The address of this information is the inode->i_ino. Just to make sure everything went well, we check it's there. */ struct smb_inode_info *inode_info = (struct smb_inode_info *)(inode->i_ino); #if 1 struct smb_inode_info *root = &(SMB_SERVER(inode)->root); struct smb_inode_info *check_info = root; do { if (inode_info == check_info) { if (check_info->state == SMB_INODE_LOOKED_UP) { DDPRINTK("smb_read_inode: found it!\n"); goto good; } else { printk("smb_read_inode: " "state != SMB_INODE_LOOKED_UP\n"); return; } } check_info = check_info->next; } while (check_info != root); /* Ok, now we're in trouble. The inode info is not there. What should we do now??? */ printk("smb_read_inode: inode info not found\n"); return; good: #endif inode_info->state = SMB_INODE_VALID; SMB_INOP(inode) = inode_info; if (SMB_INOP(inode)->finfo.attr & aDIR) inode->i_mode = SMB_SERVER(inode)->m.dir_mode; else inode->i_mode = SMB_SERVER(inode)->m.file_mode; DDPRINTK("smb_read_inode: inode->i_mode = %u\n", inode->i_mode); inode->i_nlink = 1; inode->i_uid = SMB_SERVER(inode)->m.uid; inode->i_gid = SMB_SERVER(inode)->m.gid; inode->i_size = SMB_INOP(inode)->finfo.size; inode->i_blksize = 1024; inode->i_rdev = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) inode->i_blocks = (inode->i_size - 1) / inode->i_blksize + 1; else inode->i_blocks = 0; inode->i_mtime = SMB_INOP(inode)->finfo.mtime; inode->i_ctime = SMB_INOP(inode)->finfo.ctime; inode->i_atime = SMB_INOP(inode)->finfo.atime; if (S_ISREG(inode->i_mode)) inode->i_op = &smb_file_inode_operations; else if (S_ISDIR(inode->i_mode)) inode->i_op = &smb_dir_inode_operations; else inode->i_op = NULL; }
static int ncp_do_request(struct ncp_server *server, int size, void* reply, int max_reply_size) { int result; if (server->lock == 0) { printk(KERN_ERR "ncpfs: Server not locked!\n"); return -EIO; } if (!ncp_conn_valid(server)) { printk(KERN_ERR "ncpfs: Connection invalid!\n"); return -EIO; } { mm_segment_t fs; sigset_t old_set; unsigned long mask, flags; spin_lock_irqsave(¤t->sighand->siglock, flags); old_set = current->blocked; if (current->flags & PF_EXITING) mask = 0; else mask = sigmask(SIGKILL); if (server->m.flags & NCP_MOUNT_INTR) { /* FIXME: This doesn't seem right at all. So, like, we can't handle SIGINT and get whatever to stop? What if we've blocked it ourselves? What about alarms? Why, in fact, are we mucking with the sigmask at all? -- r~ */ if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGINT); if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGQUIT); } siginitsetinv(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); fs = get_fs(); set_fs(get_ds()); result = do_ncp_rpc_call(server, size, reply, max_reply_size); set_fs(fs); spin_lock_irqsave(¤t->sighand->siglock, flags); current->blocked = old_set; recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); } DDPRINTK("do_ncp_rpc_call returned %d\n", result); if (result < 0) { /* There was a problem with I/O, so the connections is * no longer usable. */ ncp_invalidate_conn(server); } return result; }
static int do_ncp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header* reply_buf, int max_reply_size) { struct file *file; struct socket *sock; int result; char *start = server->packet; poll_table wait_table; int init_timeout, max_timeout; int timeout; int retrans; int major_timeout_seen; int acknowledge_seen; int n; /* We have to check the result, so store the complete header */ struct ncp_request_header request = *((struct ncp_request_header *) (server->packet)); struct ncp_reply_header reply; file = server->ncp_filp; sock = &file->f_dentry->d_inode->u.socket_i; init_timeout = server->m.time_out; max_timeout = NCP_MAX_RPC_TIMEOUT; retrans = server->m.retry_count; major_timeout_seen = 0; acknowledge_seen = 0; for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) { /* DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", htonl(server->m.serv_addr.sipx_network), server->m.serv_addr.sipx_node[0], server->m.serv_addr.sipx_node[1], server->m.serv_addr.sipx_node[2], server->m.serv_addr.sipx_node[3], server->m.serv_addr.sipx_node[4], server->m.serv_addr.sipx_node[5], ntohs(server->m.serv_addr.sipx_port)); */ DDPRINTK("ncpfs: req.typ: %04X, con: %d, " "seq: %d", request.type, (request.conn_high << 8) + request.conn_low, request.sequence); DDPRINTK(" func: %d\n", request.function); result = _send(sock, (void *) start, size); if (result < 0) { printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result); break; } re_select: poll_initwait(&wait_table); /* mb() is not necessary because ->poll() will serialize instructions adding the wait_table waitqueues in the waitqueue-head before going to calculate the mask-retval. */ __set_current_state(TASK_INTERRUPTIBLE); if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) { int timed_out; if (timeout > max_timeout) { /* JEJB/JSP 2/7/94 * This is useful to see if the system is * hanging */ if (acknowledge_seen == 0) { printk(KERN_WARNING "NCP max timeout\n"); } timeout = max_timeout; } timed_out = !schedule_timeout(timeout); poll_freewait(&wait_table); current->state = TASK_RUNNING; if (signal_pending(current)) { result = -ERESTARTSYS; break; } if(wait_table.error) { result = wait_table.error; break; } if (timed_out) { if (n < retrans) continue; if (server->m.flags & NCP_MOUNT_SOFT) { printk(KERN_WARNING "NCP server not responding\n"); result = -EIO; break; } n = 0; timeout = init_timeout; if (init_timeout < max_timeout) init_timeout <<= 1; if (!major_timeout_seen) { printk(KERN_WARNING "NCP server not responding\n"); } major_timeout_seen = 1; continue; } } else { poll_freewait(&wait_table); } current->state = TASK_RUNNING; /* Get the header from the next packet using a peek, so keep it * on the recv queue. If it is wrong, it will be some reply * we don't now need, so discard it */ result = _recv(sock, (void *) &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); if (result < 0) { if (result == -EAGAIN) { DDPRINTK("ncp_rpc_call: bad select ready\n"); goto re_select; } if (result == -ECONNREFUSED) { DPRINTK("ncp_rpc_call: server playing coy\n"); goto re_select; } if (result != -ERESTARTSYS) { printk(KERN_ERR "ncp_rpc_call: recv error = %d\n", -result); } break; } if ((result == sizeof(reply)) && (reply.type == NCP_POSITIVE_ACK)) { /* Throw away the packet */ DPRINTK("ncp_rpc_call: got positive acknowledge\n"); _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); n = 0; timeout = max_timeout; acknowledge_seen = 1; goto re_select; } DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d," "seq: %d\n", reply.type, (reply.conn_high << 8) + reply.conn_low, reply.task, reply.sequence); if ((result >= sizeof(reply)) && (reply.type == NCP_REPLY) && ((request.type == NCP_ALLOC_SLOT_REQUEST) || ((reply.sequence == request.sequence) && (reply.conn_low == request.conn_low) /* seem to get wrong task from NW311 && (reply.task == request.task) */ && (reply.conn_high == request.conn_high)))) { if (major_timeout_seen) printk(KERN_NOTICE "NCP server OK\n"); break; } /* JEJB/JSP 2/7/94 * we have xid mismatch, so discard the packet and start * again. What a hack! but I can't call recvfrom with * a null buffer yet. */ _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); DPRINTK("ncp_rpc_call: reply mismatch\n"); goto re_select; } /* * we have the correct reply, so read into the correct place and * return it */ result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT); if (result < 0) { printk(KERN_WARNING "NCP: notice message: result=%d\n", result); } else if (result < sizeof(struct ncp_reply_header)) { printk(KERN_ERR "NCP: just caught a too small read memory size..., " "email to NET channel\n"); printk(KERN_ERR "NCP: result=%d\n", result); result = -EIO; } return result; }
static int ncp_do_request(struct ncp_server *server, int size, void* reply, int max_reply_size) { struct file *file; struct socket *sock; int result; if (server->lock == 0) { printk(KERN_ERR "ncpfs: Server not locked!\n"); return -EIO; } if (!ncp_conn_valid(server)) { return -EIO; } #ifdef CONFIG_NCPFS_PACKET_SIGNING if (server->sign_active) { sign_packet(server, &size); } #endif /* CONFIG_NCPFS_PACKET_SIGNING */ file = server->ncp_filp; sock = &file->f_dentry->d_inode->u.socket_i; /* N.B. this isn't needed ... check socket type? */ if (!sock) { printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n"); result = -EBADF; } else { mm_segment_t fs; sigset_t old_set; unsigned long mask, flags; spin_lock_irqsave(¤t->sigmask_lock, flags); old_set = current->blocked; if (current->flags & PF_EXITING) mask = 0; else mask = sigmask(SIGKILL); if (server->m.flags & NCP_MOUNT_INTR) { /* FIXME: This doesn't seem right at all. So, like, we can't handle SIGINT and get whatever to stop? What if we've blocked it ourselves? What about alarms? Why, in fact, are we mucking with the sigmask at all? -- r~ */ if (current->sig->action[SIGINT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGINT); if (current->sig->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGQUIT); } siginitsetinv(¤t->blocked, mask); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); fs = get_fs(); set_fs(get_ds()); if (sock->type == SOCK_STREAM) result = do_ncp_tcp_rpc_call(server, size, reply, max_reply_size); else result = do_ncp_rpc_call(server, size, reply, max_reply_size); set_fs(fs); spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = old_set; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } DDPRINTK("do_ncp_rpc_call returned %d\n", result); if (result < 0) { /* There was a problem with I/O, so the connections is * no longer usable. */ ncp_invalidate_conn(server); } return result; }
static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header* reply_buf, int max_reply_size) { struct file *file; struct socket *sock; int result; struct iovec iov[2]; struct msghdr msg; struct scm_cookie scm; __u32 ncptcp_rcvd_hdr[2]; __u32 ncptcp_xmit_hdr[4]; int datalen; /* We have to check the result, so store the complete header */ struct ncp_request_header request = *((struct ncp_request_header *) (server->packet)); file = server->ncp_filp; sock = &file->f_dentry->d_inode->u.socket_i; ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC); ncptcp_xmit_hdr[1] = htonl(size + 16); ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION); ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8); DDPRINTK("ncpfs: req.typ: %04X, con: %d, " "seq: %d", request.type, (request.conn_high << 8) + request.conn_low, request.sequence); DDPRINTK(" func: %d\n", request.function); iov[1].iov_base = (void *) server->packet; iov[1].iov_len = size; iov[0].iov_base = ncptcp_xmit_hdr; iov[0].iov_len = 16; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_iov = iov; msg.msg_iovlen = 2; msg.msg_flags = MSG_NOSIGNAL; result = scm_send(sock, &msg, &scm); if (result < 0) { return result; } result = sock->ops->sendmsg(sock, &msg, size + 16, &scm); scm_destroy(&scm); if (result < 0) { printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result); return result; } rstrcv: result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8); if (result) return result; if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) { printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0])); return -EIO; } datalen = ntohl(ncptcp_rcvd_hdr[1]); if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) { printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); return -EIO; } datalen -= 8; result = do_tcp_rcv(server, reply_buf, datalen); if (result) return result; if (reply_buf->type != NCP_REPLY) { DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type); goto rstrcv; } if (request.type == NCP_ALLOC_SLOT_REQUEST) return datalen; if (reply_buf->sequence != request.sequence) { printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); return -EIO; } if ((reply_buf->conn_low != request.conn_low) || (reply_buf->conn_high != request.conn_high)) { printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); return -EIO; } return datalen; }
static int do_ncp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header* reply_buf, int max_reply_size) { struct file *file; struct inode *inode; struct socket *sock; mm_segment_t fs; int result; char *start = server->packet; poll_table wait_table; struct poll_table_entry entry; int init_timeout, max_timeout; int timeout; int retrans; int major_timeout_seen; int acknowledge_seen; int n; sigset_t old_set; unsigned long mask, flags; /* We have to check the result, so store the complete header */ struct ncp_request_header request = *((struct ncp_request_header *) (server->packet)); struct ncp_reply_header reply; file = server->ncp_filp; inode = file->f_dentry->d_inode; sock = &inode->u.socket_i; /* N.B. this isn't needed ... check socket type? */ if (!sock) { printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n"); return -EBADF; } init_timeout = server->m.time_out; max_timeout = NCP_MAX_RPC_TIMEOUT; retrans = server->m.retry_count; major_timeout_seen = 0; acknowledge_seen = 0; spin_lock_irqsave(¤t->sigmask_lock, flags); old_set = current->blocked; mask = sigmask(SIGKILL) | sigmask(SIGSTOP); if (server->m.flags & NCP_MOUNT_INTR) { /* FIXME: This doesn't seem right at all. So, like, we can't handle SIGINT and get whatever to stop? What if we've blocked it ourselves? What about alarms? Why, in fact, are we mucking with the sigmask at all? -- r~ */ if (current->sig->action[SIGINT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGINT); if (current->sig->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) mask |= sigmask(SIGQUIT); } siginitsetinv(¤t->blocked, mask); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); fs = get_fs(); set_fs(get_ds()); for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) { /* DDPRINTK(KERN_DEBUG "ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", htonl(server->m.serv_addr.sipx_network), server->m.serv_addr.sipx_node[0], server->m.serv_addr.sipx_node[1], server->m.serv_addr.sipx_node[2], server->m.serv_addr.sipx_node[3], server->m.serv_addr.sipx_node[4], server->m.serv_addr.sipx_node[5], ntohs(server->m.serv_addr.sipx_port)); */ DDPRINTK(KERN_DEBUG "ncpfs: req.typ: %04X, con: %d, " "seq: %d", request.type, (request.conn_high << 8) + request.conn_low, request.sequence); DDPRINTK(KERN_DEBUG " func: %d\n", request.function); result = _send(sock, (void *) start, size); if (result < 0) { printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result); break; } re_select: wait_table.nr = 0; wait_table.entry = &entry; current->state = TASK_INTERRUPTIBLE; if (!(file->f_op->poll(file, &wait_table) & POLLIN)) { int timed_out; if (timeout > max_timeout) { /* JEJB/JSP 2/7/94 * This is useful to see if the system is * hanging */ if (acknowledge_seen == 0) { printk(KERN_WARNING "NCP max timeout\n"); } timeout = max_timeout; } timed_out = !schedule_timeout(timeout); remove_wait_queue(entry.wait_address, &entry.wait); fput(file); current->state = TASK_RUNNING; if (signal_pending(current)) { result = -ERESTARTSYS; break; } if (timed_out) { if (n < retrans) continue; if (server->m.flags & NCP_MOUNT_SOFT) { printk(KERN_WARNING "NCP server not responding\n"); result = -EIO; break; } n = 0; timeout = init_timeout; init_timeout <<= 1; if (!major_timeout_seen) { printk(KERN_WARNING "NCP server not responding\n"); } major_timeout_seen = 1; continue; } } else if (wait_table.nr) { remove_wait_queue(entry.wait_address, &entry.wait); fput(file); } current->state = TASK_RUNNING; /* Get the header from the next packet using a peek, so keep it * on the recv queue. If it is wrong, it will be some reply * we don't now need, so discard it */ result = _recv(sock, (void *) &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); if (result < 0) { if (result == -EAGAIN) { DDPRINTK(KERN_DEBUG "ncp_rpc_call: bad select ready\n"); goto re_select; } if (result == -ECONNREFUSED) { DPRINTK(KERN_WARNING "ncp_rpc_call: server playing coy\n"); goto re_select; } if (result != -ERESTARTSYS) { printk(KERN_ERR "ncp_rpc_call: recv error = %d\n", -result); } break; } if ((result == sizeof(reply)) && (reply.type == NCP_POSITIVE_ACK)) { /* Throw away the packet */ DPRINTK(KERN_DEBUG "ncp_rpc_call: got positive acknowledge\n"); _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); n = 0; timeout = max_timeout; acknowledge_seen = 1; goto re_select; } DDPRINTK(KERN_DEBUG "ncpfs: rep.typ: %04X, con: %d, tsk: %d," "seq: %d\n", reply.type, (reply.conn_high << 8) + reply.conn_low, reply.task, reply.sequence); if ((result >= sizeof(reply)) && (reply.type == NCP_REPLY) && ((request.type == NCP_ALLOC_SLOT_REQUEST) || ((reply.sequence == request.sequence) && (reply.conn_low == request.conn_low) /* seem to get wrong task from NW311 && (reply.task == request.task) */ && (reply.conn_high == request.conn_high)))) { if (major_timeout_seen) printk(KERN_NOTICE "NCP server OK\n"); break; } /* JEJB/JSP 2/7/94 * we have xid mismatch, so discard the packet and start * again. What a hack! but I can't call recvfrom with * a null buffer yet. */ _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); DPRINTK(KERN_WARNING "ncp_rpc_call: reply mismatch\n"); goto re_select; } /* * we have the correct reply, so read into the correct place and * return it */ result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT); if (result < 0) { printk(KERN_WARNING "NCP: notice message: result=%d\n", result); } else if (result < sizeof(struct ncp_reply_header)) { printk(KERN_ERR "NCP: just caught a too small read memory size..., " "email to NET channel\n"); printk(KERN_ERR "NCP: result=%d\n", result); result = -EIO; } spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = old_set; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); set_fs(fs); return result; }
/* * Fill in the supplied page for mmap */ static unsigned long smb_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { struct inode *inode = area->vm_inode; unsigned long page; unsigned int clear; unsigned long tmp; int n; int i; int pos; page = __get_free_page(GFP_KERNEL); if (!page) return 0; address &= PAGE_MASK; pos = address - area->vm_start + area->vm_offset; clear = 0; if (address + PAGE_SIZE > area->vm_end) { clear = address + PAGE_SIZE - area->vm_end; } /* what we can read in one go */ n = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 3 - 10; if (smb_make_open(inode, O_RDONLY) < 0) { clear = PAGE_SIZE; } else { for (i = 0; i < (PAGE_SIZE - clear); i += n) { int hunk, result; hunk = PAGE_SIZE - i; if (hunk > n) hunk = n; DDPRINTK("smb_file_mmap_nopage: reading\n"); DDPRINTK("smb_file_mmap_nopage: pos = %d\n", pos); result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode), pos, hunk, (char *) (page + i), 0); DDPRINTK("smb_file_mmap_nopage: result= %d\n", result); if (result < 0) break; pos += result; if (result < n) { i += result; break; } } } tmp = page + PAGE_SIZE; while (clear--) { *(char *) --tmp = 0; } return page; }
static void ncp_read_inode(struct inode *inode) { /* Our task should be extremely simple here. We only have to look up the information somebody else (ncp_iget) put into the inode tree. The address of this information is the inode->i_ino. Just to make sure everything went well, we check it's there. */ struct ncp_inode_info *inode_info = ncp_find_inode(inode); if (inode_info == NULL) { /* Ok, now we're in trouble. The inode info is not there. What should we do now??? */ printk("ncp_read_inode: inode info not found\n"); return; } inode_info->state = NCP_INODE_VALID; NCP_INOP(inode) = inode_info; inode_info->inode = inode; if (NCP_ISTRUCT(inode)->attributes & aDIR) { inode->i_mode = NCP_SERVER(inode)->m.dir_mode; /* for directories dataStreamSize seems to be some Object ID ??? */ inode->i_size = 512; } else { inode->i_mode = NCP_SERVER(inode)->m.file_mode; inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize; } DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); inode->i_nlink = 1; inode->i_uid = NCP_SERVER(inode)->m.uid; inode->i_gid = NCP_SERVER(inode)->m.gid; inode->i_blksize = 512; inode->i_rdev = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) { inode->i_blocks = (inode->i_size - 1) / inode->i_blksize + 1; } else { inode->i_blocks = 0; } inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime, NCP_ISTRUCT(inode)->modifyDate); inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime, NCP_ISTRUCT(inode)->creationDate); inode->i_atime = ncp_date_dos2unix(0, NCP_ISTRUCT(inode)->lastAccessDate); if (S_ISREG(inode->i_mode)) { inode->i_op = &ncp_file_inode_operations; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ncp_dir_inode_operations; } else { inode->i_op = NULL; } }
/* 7 bytes max write! first byte bit 7 - flush buffer (buffer will only contain result of this command) bit 6 - query? (1 = query/read, 0 = set/write) if query is set, this is a single byte command bit 5 - PORTA dir present "@00D0%02X\r" bit 4 - PORTB dir present "@00D1%02X\r" bit 3 - PORTC dir present "@00D2%02X\r" bit 2 - PORTA data present "@00P0%02X\r" bit 1 - PORTB data present "@00P1%02X\r" bit 0 - PORTC data present "@00P2%02X\r" */ static ssize_t diodev_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos) { #define CMDSEP "\r" //#define CMDSEP "-" struct usb_dio_dev *dev; struct usb_dio_urb_chain *bulk_out_urb_chain; struct usb_dio_urb_chain *t_urb_chain; struct urb *urb; char *urbBuf; unsigned char buf[7]; int ptr; unsigned char usbBuf[64]; /* max of 48 bytes possible */ int usbBytes = 0; int isQuery = 0; int retval; FUNC_HI(); dev = (struct usb_dio_dev *)file->private_data; if (count > 7) { printk(KERN_ALERT "=== Too many bytes! (%d)\n", (int)count); FUNC_ERR(); return -EIO; } if (copy_from_user(&(buf[0]),user_buffer,count)) { printk(KERN_ALERT "=== Copy error\n"); FUNC_ERR(); return -EIO; } if (buf[0] & 0x80) { if (down_interruptible(&dev->buffer_sem)) { FUNC_ERR(); return -EINTR; } dev->buffer_head = 0; dev->buffer_tail = 0; up(&dev->buffer_sem); DPRINTK(KERN_ALERT "=== Flushed\n"); } if (buf[0] & 0x40) { isQuery = 1; DPRINTK(KERN_ALERT "=== isQuery\n"); } /* if is a query... we only need 1 byte! */ if (buf[0] & 0x40) { DPRINTK(KERN_ALERT "=== Looking for %d bytes...\n",1); DPRINTK(KERN_ALERT "=== Given %d bytes...\n", (int)count); if (count != 1) { FUNC_ERR(); return -EIO; } } else { int c = 1; unsigned char t = 0x20; while (t) { if (buf[0] & t) c++; t >>= 1; t &= 0x7F; } DPRINTK(KERN_ALERT "=== Looking for %d bytes...\n",c); DPRINTK(KERN_ALERT "=== Given %d bytes...\n", (int)count); if (count != c) { FUNC_ERR(); return -EIO; } } if (isQuery) { DDPRINTK("Q-"); } else { DDPRINTK("W-"); } ptr = 1; if (buf[0] & 0x20) { DDPRINTK("d0"); DPRINTK(KERN_ALERT "=== D0\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D0?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D0%02X"CMDSEP,buf[ptr]); ptr++; } } if (buf[0] & 0x10) { DDPRINTK("d1"); DPRINTK(KERN_ALERT "=== D1\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D1?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D1%02X"CMDSEP,buf[ptr]); ptr++; } } if (buf[0] & 0x08) { DDPRINTK("d2"); DPRINTK(KERN_ALERT "=== D2\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D2?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D2%02X"CMDSEP,buf[ptr]); ptr++; } } if (buf[0] & 0x04) { DDPRINTK("p0"); DPRINTK(KERN_ALERT "=== P0\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P0?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P0%02X"CMDSEP,buf[ptr]); ptr++; } } if (buf[0] & 0x02) { DDPRINTK("p1"); DPRINTK(KERN_ALERT "=== P1\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P1?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P1%02X"CMDSEP,buf[ptr]); ptr++; } } if (buf[0] & 0x01) { DDPRINTK("p2"); DPRINTK(KERN_ALERT "=== P2\n"); if (isQuery) { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P2?"CMDSEP); } else { usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P2%02X"CMDSEP,buf[ptr]); ptr++; } } DPRINTK(KERN_ALERT "=== STRING:- %s\n",usbBuf); DPRINTK(KERN_ALERT "=== Building URB...\n"); urb = usb_alloc_urb(0, GFP_KERNEL); DPRINTK(KERN_ALERT "** urb @ %p\n",urb); if (!urb) { FUNC_ERR(); return -ENOMEM; } DPRINTK(KERN_ALERT "=== Building Buffer (%d)...\n",usbBytes); urbBuf = usb_buffer_alloc(dev->dev, usbBytes, GFP_KERNEL, &urb->transfer_dma); DPRINTK(KERN_ALERT "** urbBuf @ %p\n",urbBuf); if (!urbBuf) { usb_free_urb(urb); FUNC_ERR(); return -ENOMEM; } DPRINTK(KERN_ALERT "=== Populating Buffer...\n"); memcpy(urbBuf, usbBuf, usbBytes); usb_fill_bulk_urb(urb, dev->dev, dev->bulk_out_endpointPipe, urbBuf, usbBytes, (usb_complete_t)diodev_write_cb, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; t_urb_chain = kmalloc(sizeof(struct usb_dio_urb_chain), GFP_KERNEL); if (dev == NULL) { err("Out of Memory"); FUNC_ERR(); return -ENOMEM; } t_urb_chain->next = NULL; t_urb_chain->urb = urb; if (down_interruptible(&dev->bulk_out_urb_chain_sem)) { FUNC_ERR(); return -EINTR; } if (dev->bulk_out_urb_chain) { DDPRINTK("-C"); DPRINTK(KERN_ALERT "=== Chaining URB...\n"); bulk_out_urb_chain = dev->bulk_out_urb_chain; while (bulk_out_urb_chain->next) { bulk_out_urb_chain = bulk_out_urb_chain->next; } bulk_out_urb_chain->next = t_urb_chain; } else { DDPRINTK("-S"); DPRINTK(KERN_ALERT "=== Submitting URB...\n"); retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { up(&dev->bulk_out_urb_chain_sem); DPRINTK(KERN_ALERT "=== URB submit error %d\n", retval); usb_buffer_free(dev->dev, usbBytes, urbBuf, urb->transfer_dma); usb_free_urb(urb); FUNC_ERR(); return retval; } dev->bulk_out_urb_chain = t_urb_chain; } DDPRINTK("\n"); up(&dev->bulk_out_urb_chain_sem); DPRINTK(KERN_ALERT "=== diodev_write() Returning!\n"); FUNC_BYE(); return count; }
void diodev_rx_work(struct work_struct *work) { struct usb_dio_workitem *workitem; struct usb_dio_dev *dev; FUNC_HI(); workitem = (struct usb_dio_workitem*)work; dev = workitem->dev; DPRINTK(KERN_ALERT "=== diodev_rx_work() hello\n"); if (!workitem->arg) { DPRINTK(KERN_ALERT "=== diodev_rx_work() NULL arg!?\n"); } else { struct urb *urb; char *buf; int i; int p; char t[128]; DPRINTK(KERN_ALERT "=== diodev_rx_work() non-null arg!\n"); urb = workitem->arg; DPRINTK(KERN_ALERT "=== diodev_rx_work() %d\n",urb->actual_length); buf = (char *)urb->transfer_buffer; for (i = 0; i < 127 && i < urb->actual_length; i++) { t[i] = buf[i]; if (t[i] == '\r') t[i] = '-'; } t[i] = '\0'; DPRINTK(KERN_ALERT "### Recieved [%s] ###\n", t); DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail); /* if we have a valid return value */ DDPRINTK("R"); if (urb->actual_length == 6 && buf[0] == '!' && buf[1] == '0' && buf[2] == '0' && buf[5] == '\r') { char t[3]; unsigned char c; t[0] = buf[3]; t[1] = buf[4]; t[2] = '\0'; sscanf(t,"%02X",(unsigned int *)&c); DPRINTK(KERN_ALERT "### Recieved 0x%02X ###\n", c); if (down_interruptible(&dev->buffer_sem)) { workitem->arg = NULL; diodev_rx_setup(dev); FUNC_ERR(); return; } DPRINTK(KERN_ALERT "=== diodev_rx_work() success down(buffer_sem)...\n"); if (!((dev->buffer_tail == USB_DIO_DEV_BUFFERSIZE && dev->buffer_head == 0) || (dev->buffer_tail == dev->buffer_head - 1))) { dev->buffer[dev->buffer_tail] = c; dev->buffer_tail++; if (dev->buffer_tail >= USB_DIO_DEV_BUFFERSIZE) dev->buffer_tail = 0; DPRINTK(KERN_ALERT "### Added to buffer...\n"); /* if the lock fails... then it is already locked, so unlock it! */ /* if the lock succeeds... then it is not already locked, but is now... so unlock it! */ p = down_trylock(&dev->buffer_empty_sem); DPRINTK(KERN_ALERT "### Kicking sem...\n"); up(&dev->buffer_empty_sem); DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail); } else { DPRINTK(KERN_ALERT "### Buffer full...\n"); } DDPRINTK("-0x%02X", c); up(&dev->buffer_sem); } else { DDPRINTK("-X"); } DDPRINTK("\n"); DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail); usb_buffer_free(dev->dev, dev->bulk_in_size, urb->transfer_buffer, urb->transfer_dma); usb_free_urb(urb); } workitem->arg = NULL; diodev_rx_setup(dev); DPRINTK(KERN_ALERT "=== diodev_rx_work() returning\n"); FUNC_BYE(); }