?? proc.c
字號:
smb_setup_header_exclusive(server, SMBread, 5, 0); buf = server->packet; WSET(buf, smb_vwv0, finfo->fileid); WSET(buf, smb_vwv1, count); DSET(buf, smb_vwv2, offset); WSET(buf, smb_vwv4, 0); if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0) { smb_unlock_server(server); return error; } returned_count = WVAL(server->packet, smb_vwv0); smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs); smb_unlock_server(server); if (returned_count != data_len) { printk("smb_proc_read: Warning, returned_count != data_len\n"); printk("smb_proc_read: ret_c=%d, data_len=%d\n", returned_count, data_len); } return data_len;}intsmb_proc_write(struct smb_server *server, struct smb_dirent *finfo, off_t offset, int count, const char *data){ int res = 0; char *buf; byte *p; p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3); buf = server->packet; WSET(buf, smb_vwv0, finfo->fileid); WSET(buf, smb_vwv1, count); DSET(buf, smb_vwv2, offset); WSET(buf, smb_vwv4, 0); *p++ = 1; WSET(p, 0, count); memcpy_fromfs(p + 2, data, count); if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) { res = WVAL(server->packet, smb_vwv0); } smb_unlock_server(server); return res;}intsmb_proc_create(struct inode *dir, const char *name, int len, word attr, time_t ctime){ int error; char *p; struct smb_server *server = SMB_SERVER(dir); char *buf; __u16 fileid; smb_lock_server(server); retry: buf = server->packet; p = smb_setup_header(server, SMBcreate, 3, 0); WSET(buf, smb_vwv0, attr); DSET(buf, smb_vwv1, utc2local(ctime)); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), name, len); smb_setup_bcc(server, p); if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0) { if (smb_retry(server)) { goto retry; } smb_unlock_server(server); return error; } fileid = WVAL(server->packet, smb_vwv0); smb_unlock_server(server); smb_proc_close(server, fileid, CURRENT_TIME); return 0;}intsmb_proc_mv(struct inode *odir, const char *oname, const int olen, struct inode *ndir, const char *nname, const int nlen){ char *p; struct smb_server *server = SMB_SERVER(odir); int result; smb_lock_server(server); retry: p = smb_setup_header(server, SMBmv, 1, 0); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(odir), oname, olen); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(ndir), nname, nlen); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}intsmb_proc_mkdir(struct inode *dir, const char *name, const int len){ char *p; int result; struct smb_server *server = SMB_SERVER(dir); smb_lock_server(server); retry: p = smb_setup_header(server, SMBmkdir, 0, 0); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), name, len); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}intsmb_proc_rmdir(struct inode *dir, const char *name, const int len){ char *p; int result; struct smb_server *server = SMB_SERVER(dir); smb_lock_server(server); retry: p = smb_setup_header(server, SMBrmdir, 0, 0); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), name, len); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}intsmb_proc_unlink(struct inode *dir, const char *name, const int len){ char *p; struct smb_server *server = SMB_SERVER(dir); int result; smb_lock_server(server); retry: p = smb_setup_header(server, SMBunlink, 1, 0); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), name, len); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}intsmb_proc_trunc(struct smb_server *server, word fid, dword length){ char *p; char *buf; int result; smb_lock_server(server); retry: buf = server->packet; p = smb_setup_header(server, SMBwrite, 5, 0); WSET(buf, smb_vwv0, fid); WSET(buf, smb_vwv1, 0); DSET(buf, smb_vwv2, length); WSET(buf, smb_vwv4, 0); p = smb_encode_ascii(p, "", 0); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}static voidsmb_init_dirent(struct smb_server *server, struct smb_dirent *entry){ memset(entry, 0, sizeof(struct smb_dirent)); entry->f_nlink = 1; entry->f_uid = server->m.uid; entry->f_gid = server->m.gid; entry->f_blksize = 512;}static voidsmb_finish_dirent(struct smb_server *server, struct smb_dirent *entry){ if ((entry->attr & aDIR) != 0) { entry->f_mode = server->m.dir_mode; entry->f_size = 512; } else { entry->f_mode = server->m.file_mode; } if (entry->attr & aRONLY) entry->f_mode &= ~0222; if ((entry->f_blksize != 0) && (entry->f_size != 0)) { entry->f_blocks = (entry->f_size - 1) / entry->f_blksize + 1; } else { entry->f_blocks = 0; } return;}voidsmb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry){ smb_init_dirent(server, entry); entry->attr = aDIR; entry->f_ino = 1; smb_finish_dirent(server, entry);}static char *smb_decode_dirent(struct smb_server *server, char *p, struct smb_dirent *entry){ smb_init_dirent(server, entry); p += SMB_STATUS_SIZE; /* reserved (search_status) */ entry->attr = BVAL(p, 0); entry->f_mtime = entry->f_atime = entry->f_ctime = date_dos2unix(WVAL(p, 1), WVAL(p, 3)); entry->f_size = DVAL(p, 5); entry->len = strlen(p + 9); if (entry->len > 12) { entry->len = 12; } memcpy(entry->name, p + 9, entry->len); entry->name[entry->len] = '\0'; while (entry->len > 2) { /* Pathworks fills names with spaces */ entry->len -= 1; if (entry->name[entry->len] == ' ') { entry->name[entry->len] = '\0'; } } switch (server->case_handling) { case CASE_UPPER: str_upper(entry->name); break; case CASE_LOWER: str_lower(entry->name); break; default: break; } DPRINTK("smb_decode_dirent: name = %s\n", entry->name); smb_finish_dirent(server, entry); return p + 22;}/* This routine is used to read in directory entries from the network. Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2 */static intsmb_proc_readdir_short(struct smb_server *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry){ char *p; char *buf; int error; int result; int i; int first, total_count; struct smb_dirent *current_entry; word bcc; word count; char status[SMB_STATUS_SIZE]; int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE; DPRINTK("SMB call readdir %d @ %d\n", cache_size, fpos); smb_lock_server(server); retry: buf = server->packet; first = 1; total_count = 0; current_entry = entry; while (1) { if (first == 1) { p = smb_setup_header(server, SMBsearch, 2, 0); WSET(buf, smb_vwv0, entries_asked); WSET(buf, smb_vwv1, aDIR); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), "*.*", 3); *p++ = 5; WSET(p, 0, 0); p += 2; } else { p = smb_setup_header(server, SMBsearch, 2, 0); WSET(buf, smb_vwv0, entries_asked); WSET(buf, smb_vwv1, aDIR); p = smb_encode_ascii(p, "", 0); *p++ = 5; WSET(p, 0, SMB_STATUS_SIZE); p += 2; memcpy(p, status, SMB_STATUS_SIZE); p += SMB_STATUS_SIZE; } smb_setup_bcc(server, p); if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0) { if ((server->rcls == ERRDOS) && (server->err == ERRnofiles)) { result = total_count - fpos; goto unlock_return; } else { if (smb_retry(server)) { goto retry; } result = error; goto unlock_return; } } p = SMB_VWV(server->packet); p = smb_decode_word(p, &count); p = smb_decode_word(p, &bcc); first = 0; if (count <= 0) { result = total_count - fpos; goto unlock_return; } if (bcc != count * SMB_DIRINFO_SIZE + 3) { result = -EIO; goto unlock_return; } p += 3; /* Skipping VBLOCK header (5, length lo, length hi). */ /* Read the last entry into the status field. */ memcpy(status, SMB_BUF(server->packet) + 3 + (count - 1) * SMB_DIRINFO_SIZE, SMB_STATUS_SIZE); /* Now we are ready to parse smb directory entries. */ for (i = 0; i < count; i++) { if (total_count < fpos) { p += SMB_DIRINFO_SIZE; DDPRINTK("smb_proc_readdir: skipped entry.\n"); DDPRINTK(" total_count = %d\n" " i = %d, fpos = %d\n", total_count, i, fpos); } else if (total_count >= fpos + cache_size) { result = total_count - fpos; goto unlock_return; } else { p = smb_decode_dirent(server, p, current_entry); current_entry->f_pos = total_count; DDPRINTK("smb_proc_readdir: entry->f_pos = " "%lu\n", entry->f_pos); current_entry += 1; } total_count += 1; } } unlock_return: smb_unlock_server(server); return result;}/* interpret a long filename structure - this is mostly guesses at the moment. The length of the structure is returned. The structure of a long filename depends on the info level. 260 is used by NT and 2 is used by OS/2. */static char *smb_decode_long_dirent(struct smb_server *server, char *p, struct smb_dirent *entry, int level){ char *result; smb_init_dirent(server, entry); switch (level) { /* We might add more levels later... */ case 1: entry->len = BVAL(p, 26); strncpy(entry->name, p + 27, entry->len); entry->name[entry->len] = '\0'; entry->f_size = DVAL(p, 16); entry->attr = BVAL(p, 24); entry->f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); entry->f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); entry->f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12)); result = p + 28 + BVAL(p, 26); break; default: DPRINTK("Unknown long filename format %d\n", level); result = p + WVAL(p, 0); } switch (server->case_handling) { case CASE_UPPER: str_upper(entry->name); break; case CASE_LOWER: str_lower(entry->name); break; default: break; } smb_finish_dirent(server, entry); return result;}intsmb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *cache){ /* NT uses 260, OS/2 uses 2. Both accept 1. */ const int info_level = 1; const int max_matches = 512; char *p; char *lastname; int lastname_len; int i; int first, entries, entries_seen; unsigned char *resp_data = NULL; unsigned char *resp_param = NULL; int resp_data_len = 0; int resp_param_len = 0; __u16 command; int result; int ff_resume_key = 0; int ff_searchcount = 0; int ff_eos = 0; int ff_lastname = 0; int ff_dir_handle = 0; int loop_count = 0; char param[SMB_MAXPATHLEN + 2 + 12]; int mask_len; unsigned char *mask = &(param[12]); mask_len = smb_encode_path(server, mask, SMB_INOP(dir), "*", 1) - mask; mask[mask_len] = 0; mask[mask_len + 1] = 0; DPRINTK("smb_readdir_long cache=%d, fpos=%d, mask=%s\n", cache_size, fpos, mask); smb_lock_server(server); retry: first = 1; entries = 0; entries_seen = 2; while (ff_eos == 0) { loop_count += 1; if (loop_count > 200) { printk("smb_proc_readdir_long: " "Looping in FIND_NEXT??\n"); break; } if (first != 0) { command = TRANSACT2_FINDFIRST; WSET(param, 0, aSYSTEM | aHIDDEN | aDIR); WSET(param, 2, max_matches); /* max count */ WSET(param, 4, 8 + 4 + 2); /* resume required + close on end + continue */ WSET(param, 6, info_level); DSET(param, 8, 0); } else { command = TRANSACT2_FINDNEXT; DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", ff_dir_handle, ff_resume_key, ff_lastname, mask); WSET(param, 0, ff_dir_handle); WSET(param, 2, max_matches); /* max count */ WSET(param, 4, info_level); DSET(param, 6, ff_resume_key); /* ff_resume_key */ WSET(param, 10, 8 + 4 + 2); /* resume required + close on end + continue */#ifdef CONFIG_SMB_WIN95 /* Windows 95 is not able to deliver answers to FIND_NEXT fast enough, so sleep 0.2 seconds */ current->timeout = jiffies + HZ / 5; current->state = TASK_INTERRUPTIBLE; schedule(); current->timeout = 0;#endif } result = smb_trans2_request(server, command, 0, NULL, 12 + mask_len + 2, param, &resp_data_len, &resp_data, &resp_param_len, &resp_param); if (result < 0) { if (smb_retry(server)) { goto retry; } DPRINTK("smb_proc_readdir_long: " "got error from trans2_request\n"); break; } if (server->rcls != 0) { result = -EIO; break; } /* parse out some important return info */ if (first != 0) { ff_dir_handle = WVAL(resp_param, 0); ff_searchcount = WVAL(resp_param, 2); ff_eos = WVAL(resp_param, 4); ff_lastname = WVAL(resp_param, 8); } else { ff_searchcount = WVAL(resp_param, 0); ff_eos = WVAL(resp_param, 2); ff_lastname = WVAL(resp_param, 6); } if (ff_searchcount == 0) { break; } /* point to the data bytes */ p = resp_data; /* we might need the lastname for continuations */ lastname = "";
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -