Import 2.1.55pre1
[davej-history.git] / fs / smbfs / proc.c
blob311457a74ac8cf32c22fb98e996d9a1c578c8729
1 /*
2 * proc.c
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
7 * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
8 */
10 #include <linux/config.h>
11 #include <linux/fs.h>
12 #include <linux/smbno.h>
13 #include <linux/smb_fs.h>
14 #include <linux/types.h>
15 #include <linux/errno.h>
16 #include <linux/malloc.h>
17 #include <linux/stat.h>
18 #include <linux/fcntl.h>
20 #include <asm/uaccess.h>
21 #include <asm/string.h>
23 #define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
24 #define SMB_CMD(packet) (*(packet+8))
25 #define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1))
26 #define SMB_BCC(packet) smb_bcc(packet)
27 #define SMB_BUF(packet) ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
29 #define SMB_DIRINFO_SIZE 43
30 #define SMB_STATUS_SIZE 21
32 static int smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc);
34 static inline int
35 min(int a, int b)
37 return a < b ? a : b;
40 static void
41 str_upper(char *name)
43 while (*name)
45 if (*name >= 'a' && *name <= 'z')
46 *name -= ('a' - 'A');
47 name++;
51 static void
52 str_lower(char *name)
54 while (*name)
56 if (*name >= 'A' && *name <= 'Z')
57 *name += ('a' - 'A');
58 name++;
62 /*****************************************************************************/
63 /* */
64 /* Encoding/Decoding section */
65 /* */
66 /*****************************************************************************/
68 __u8 *
69 smb_encode_smb_length(__u8 * p, __u32 len)
71 *p = 0;
72 *(p+1) = 0;
73 *(p+2) = (len & 0xFF00) >> 8;
74 *(p+3) = (len & 0xFF);
75 if (len > 0xFFFF)
77 *(p+1) = 1;
79 return p + 4;
82 static int smb_d_path(struct dentry * entry, char * buf)
84 if (IS_ROOT(entry)) {
85 *buf = '\\';
86 return 1;
87 } else {
88 int len = smb_d_path(entry->d_parent, buf);
90 buf += len;
91 if (len > 1) {
92 *buf++ = '\\';
93 len++;
95 memcpy(buf, entry->d_name.name, entry->d_name.len);
96 return len + entry->d_name.len;
100 static char *smb_encode_path(struct smb_sb_info *server, char *buf,
101 struct dentry *dir, struct qstr *name)
103 char *start = buf;
105 if (dir != NULL)
106 buf += smb_d_path(dir, buf);
108 if (name != NULL) {
109 *buf++ = '\\';
110 memcpy(buf, name->name, name->len);
111 buf += name->len;
112 *buf++ = 0;
115 if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
116 str_upper(start);
118 return buf;
121 /* The following are taken directly from msdos-fs */
123 /* Linear day numbers of the respective 1sts in non-leap years. */
125 static int day_n[] =
126 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
127 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
130 extern struct timezone sys_tz;
132 static int
133 utc2local(int time)
135 return time - sys_tz.tz_minuteswest * 60;
138 static int
139 local2utc(int time)
141 return time + sys_tz.tz_minuteswest * 60;
144 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
146 static int
147 date_dos2unix(unsigned short time, unsigned short date)
149 int month, year, secs;
151 month = ((date >> 5) & 15) - 1;
152 year = date >> 9;
153 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
154 ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
155 month < 2 ? 1 : 0) + 3653);
156 /* days since 1.1.70 plus 80's leap day */
157 return local2utc(secs);
161 /* Convert linear UNIX date to a MS-DOS time/date pair. */
163 static void
164 date_unix2dos(int unix_date, __u8 * date, __u8 * time)
166 int day, year, nl_day, month;
168 unix_date = utc2local(unix_date);
169 WSET(time, 0,
170 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
171 (((unix_date / 3600) % 24) << 11));
172 day = unix_date / 86400 - 3652;
173 year = day / 365;
174 if ((year + 3) / 4 + 365 * year > day)
175 year--;
176 day -= (year + 3) / 4 + 365 * year;
177 if (day == 59 && !(year & 3))
179 nl_day = day;
180 month = 2;
181 } else
183 nl_day = (year & 3) || day <= 59 ? day : day - 1;
184 for (month = 0; month < 12; month++)
185 if (day_n[month] > nl_day)
186 break;
188 WSET(date, 0,
189 nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
194 /*****************************************************************************/
195 /* */
196 /* Support section. */
197 /* */
198 /*****************************************************************************/
200 __u32
201 smb_len(__u8 * p)
203 return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3);
206 static __u16
207 smb_bcc(__u8 * packet)
209 int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16);
210 return WVAL(packet, pos);
213 /* smb_valid_packet: We check if packet fulfills the basic
214 requirements of a smb packet */
216 static int
217 smb_valid_packet(__u8 * packet)
219 return (packet[4] == 0xff
220 && packet[5] == 'S'
221 && packet[6] == 'M'
222 && packet[7] == 'B'
223 && (smb_len(packet) + 4 == SMB_HEADER_LEN
224 + SMB_WCT(packet) * 2 + SMB_BCC(packet)));
227 /* smb_verify: We check if we got the answer we expected, and if we
228 got enough data. If bcc == -1, we don't care. */
230 static int
231 smb_verify(__u8 * packet, int command, int wct, int bcc)
233 return (SMB_CMD(packet) == command &&
234 SMB_WCT(packet) >= wct &&
235 (bcc == -1 || SMB_BCC(packet) >= bcc)) ? 0 : -EIO;
238 static int
239 smb_errno(int errcls, int error)
241 if (errcls == ERRDOS)
242 switch (error)
244 case ERRbadfunc:
245 return EINVAL;
246 case ERRbadfile:
247 return ENOENT;
248 case ERRbadpath:
249 return ENOENT;
250 case ERRnofids:
251 return EMFILE;
252 case ERRnoaccess:
253 return EACCES;
254 case ERRbadfid:
255 return EBADF;
256 case ERRbadmcb:
257 return EREMOTEIO;
258 case ERRnomem:
259 return ENOMEM;
260 case ERRbadmem:
261 return EFAULT;
262 case ERRbadenv:
263 return EREMOTEIO;
264 case ERRbadformat:
265 return EREMOTEIO;
266 case ERRbadaccess:
267 return EACCES;
268 case ERRbaddata:
269 return E2BIG;
270 case ERRbaddrive:
271 return ENXIO;
272 case ERRremcd:
273 return EREMOTEIO;
274 case ERRdiffdevice:
275 return EXDEV;
276 case ERRnofiles:
277 return 0;
278 case ERRbadshare:
279 return ETXTBSY;
280 case ERRlock:
281 return EDEADLK;
282 case ERRfilexists:
283 return EEXIST;
284 case 87:
285 return 0; /* Unknown error!! */
286 /* This next error seems to occur on an mv when
287 * the destination exists */
288 case 183:
289 return EEXIST;
290 default:
291 return EIO;
292 } else if (errcls == ERRSRV)
293 switch (error)
295 case ERRerror:
296 return ENFILE;
297 case ERRbadpw:
298 return EINVAL;
299 case ERRbadtype:
300 return EIO;
301 case ERRaccess:
302 return EACCES;
303 default:
304 return EIO;
305 } else if (errcls == ERRHRD)
306 switch (error)
308 case ERRnowrite:
309 return EROFS;
310 case ERRbadunit:
311 return ENODEV;
312 case ERRnotready:
313 return EUCLEAN;
314 case ERRbadcmd:
315 return EIO;
316 case ERRdata:
317 return EIO;
318 case ERRbadreq:
319 return ERANGE;
320 case ERRbadshare:
321 return ETXTBSY;
322 case ERRlock:
323 return EDEADLK;
324 default:
325 return EIO;
326 } else if (errcls == ERRCMD)
327 return EIO;
328 return 0;
331 static inline void
332 smb_lock_server(struct smb_sb_info *server)
334 down(&(server->sem));
337 static inline void
338 smb_unlock_server(struct smb_sb_info *server)
340 up(&(server->sem));
343 /* smb_request_ok: We expect the server to be locked. Then we do the
344 request and check the answer completely. When smb_request_ok
345 returns 0, you can be quite sure that everything went well. When
346 the answer is <=0, the returned number is a valid unix errno. */
348 static int
349 smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
351 int result = 0;
352 s->rcls = 0;
353 s->err = 0;
355 if (smb_request(s) < 0)
357 pr_debug("smb_request failed\n");
358 result = -EIO;
359 } else if (smb_valid_packet(s->packet) != 0)
361 pr_debug("not a valid packet!\n");
362 result = -EIO;
363 } else if (s->rcls != 0)
365 result = -smb_errno(s->rcls, s->err);
366 } else if (smb_verify(s->packet, command, wct, bcc) != 0)
368 pr_debug("smb_verify failed\n");
369 result = -EIO;
371 return result;
374 /* smb_retry: This function should be called when smb_request_ok has
375 indicated an error. If the error was indicated because the
376 connection was killed, we try to reconnect. If smb_retry returns 0,
377 the error was indicated for another reason, so a retry would not be
378 of any use. */
380 static int
381 smb_retry(struct smb_sb_info *server)
383 if (server->state != CONN_INVALID)
385 return 0;
387 if (server->sock_file != NULL)
389 close_fp(server->sock_file);
390 server->sock_file = NULL;
393 if (server->conn_pid == 0)
395 server->state = CONN_RETRIED;
396 return 0;
399 kill_proc(server->conn_pid, SIGUSR1, 0);
400 server->conn_pid = 0;
402 smb_lock_server(server);
404 if (server->sock_file != NULL)
406 server->state = CONN_VALID;
407 return 1;
409 return 0;
413 smb_offerconn(struct smb_sb_info *server)
415 if (!suser() && (current->uid != server->m.mounted_uid))
417 return -EACCES;
419 server->conn_pid = current->pid;
420 return 0;
424 smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
426 struct file *filp;
428 if (opt->fd >= NR_OPEN || !(filp = current->files->fd[opt->fd]))
430 return -EBADF;
432 if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode))
434 return -EBADF;
436 if (!suser() && (current->uid != server->m.mounted_uid))
438 return -EACCES;
440 if (server->sock_file != NULL)
442 close_fp(server->sock_file);
443 server->sock_file = NULL;
445 filp->f_count += 1;
446 server->sock_file = filp;
447 smb_catch_keepalive(server);
448 server->opt = *opt;
449 pr_debug("smb_newconn: protocol = %d\n", server->opt.protocol);
450 server->conn_pid = 0;
451 server->generation += 1;
452 smb_unlock_server(server);
453 return 0;
456 /* smb_setup_header: We completely set up the packet. You only have to
457 insert the command-specific fields */
459 __u8 *
460 smb_setup_header(struct smb_sb_info * server, __u8 command, __u16 wct, __u16 bcc)
462 __u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2;
463 __u8 *p = server->packet;
464 __u8 *buf = server->packet;
466 p = smb_encode_smb_length(p, xmit_len - 4);
468 *p++ = 0xff;
469 *p++ = 'S';
470 *p++ = 'M';
471 *p++ = 'B';
472 *p++ = command;
474 memset(p, '\0', 19);
475 p += 19;
476 p += 8;
478 WSET(buf, smb_tid, server->opt.tid);
479 WSET(buf, smb_pid, 1);
480 WSET(buf, smb_uid, server->opt.server_uid);
481 WSET(buf, smb_mid, 1);
483 if (server->opt.protocol > SMB_PROTOCOL_CORE)
485 *(buf+smb_flg) = 0x8;
486 WSET(buf, smb_flg2, 0x3);
488 *p++ = wct; /* wct */
489 p += 2 * wct;
490 WSET(p, 0, bcc);
491 return p + 2;
494 static void
495 smb_setup_bcc(struct smb_sb_info *server, __u8 * p)
497 __u8 *packet = server->packet;
498 __u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet);
499 __u16 bcc = p - (pbcc + 2);
501 WSET(pbcc, 0, bcc);
502 smb_encode_smb_length(packet,
503 SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc);
508 * We're called with the server locked, and we leave it that way. We
509 * try maximum permissions.
512 static int
513 smb_proc_open(struct dentry *dir)
515 struct inode *ino = dir->d_inode;
516 struct smb_sb_info *server = SMB_SERVER(ino);
517 int error;
518 char *p;
520 retry:
521 p = smb_setup_header(server, SMBopen, 2, 0);
522 WSET(server->packet, smb_vwv0, 0x42); /* read/write */
523 WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
524 *p++ = 4;
525 p = smb_encode_path(server, p, dir, NULL);
526 smb_setup_bcc(server, p);
528 if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)
530 if (smb_retry(server))
531 goto retry;
533 if ((error != -EACCES) && (error != -ETXTBSY)
534 && (error != -EROFS))
535 return error;
537 p = smb_setup_header(server, SMBopen, 2, 0);
538 WSET(server->packet, smb_vwv0, 0x40); /* read only */
539 WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
540 *p++ = 4;
541 p = smb_encode_path(server, p, dir, NULL);
542 smb_setup_bcc(server, p);
544 if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)
546 if (smb_retry(server))
547 goto retry;
549 return error;
552 /* We should now have data in vwv[0..6]. */
554 ino->u.smbfs_i.fileid = WVAL(server->packet, smb_vwv0);
555 ino->u.smbfs_i.attr = WVAL(server->packet, smb_vwv1);
556 ino->u.smbfs_i.access = WVAL(server->packet, smb_vwv6);
557 ino->u.smbfs_i.access &= 3;
559 ino->u.smbfs_i.open = server->generation;
561 pr_debug("smb_proc_open: entry->access = %d\n", ino->u.smbfs_i.access);
562 return 0;
566 smb_open(struct dentry *dir, int wish)
568 struct inode *i=dir->d_inode;
569 struct smb_sb_info *server = SMB_SERVER(i);
570 int result = -EACCES;
572 smb_lock_server(server);
574 if (!smb_is_open(i)) {
575 int error = smb_proc_open(dir);
576 if (error) {
577 smb_unlock_server(server);
578 return error;
582 if (((wish == O_RDONLY) && ((i->u.smbfs_i.access == O_RDONLY)
583 || (i->u.smbfs_i.access == O_RDWR)))
584 || ((wish == O_WRONLY) && ((i->u.smbfs_i.access == O_WRONLY)
585 || (i->u.smbfs_i.access == O_RDWR)))
586 || ((wish == O_RDWR) && (i->u.smbfs_i.access == O_RDWR)))
587 result = 0;
589 smb_unlock_server(server);
590 return result;
593 /* We're called with the server locked */
595 static int smb_proc_close(struct smb_sb_info *server,
596 __u16 fileid, __u32 mtime)
598 smb_setup_header(server, SMBclose, 3, 0);
599 WSET(server->packet, smb_vwv0, fileid);
600 DSET(server->packet, smb_vwv1, mtime);
601 return smb_request_ok(server, SMBclose, 0, 0);
605 int smb_close(struct dentry *dir)
607 struct inode *ino = dir->d_inode;
608 struct smb_sb_info *server = SMB_SERVER(ino);
609 int result;
611 smb_lock_server(server);
613 if (!smb_is_open(ino)) {
614 smb_unlock_server(server);
615 return 0;
618 result = smb_proc_close(server, ino->u.smbfs_i.fileid, ino->i_mtime);
619 ino->u.smbfs_i.open = 0;
620 smb_unlock_server(server);
621 return result;
624 /* In smb_proc_read and smb_proc_write we do not retry, because the
625 file-id would not be valid after a reconnection. */
627 /* smb_proc_read: fs indicates if it should be copied with
628 copy_to_user. */
631 smb_proc_read(struct inode *ino, off_t offset, long count, char *data)
633 struct smb_sb_info *server = SMB_SERVER(ino);
634 __u16 returned_count, data_len;
635 char *buf;
636 int error;
638 smb_lock_server(server);
639 smb_setup_header(server, SMBread, 5, 0);
640 buf = server->packet;
642 WSET(buf, smb_vwv0, ino->u.smbfs_i.fileid);
643 WSET(buf, smb_vwv1, count);
644 DSET(buf, smb_vwv2, offset);
645 WSET(buf, smb_vwv4, 0);
647 if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0)
649 smb_unlock_server(server);
650 return error;
652 returned_count = WVAL(buf, smb_vwv0);
654 buf = SMB_BUF(server->packet);
655 data_len = WVAL(buf, 1);
657 memcpy(data, buf+3, data_len);
659 smb_unlock_server(server);
661 if (returned_count != data_len)
663 printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
664 printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
665 returned_count, data_len);
667 return data_len;
671 smb_proc_write(struct inode *ino, off_t offset, int count, const char *data)
673 struct smb_sb_info *server = SMB_SERVER(ino);
674 int res = 0;
675 __u8 *p;
677 smb_lock_server(server);
678 p = smb_setup_header(server, SMBwrite, 5, count + 3);
679 WSET(server->packet, smb_vwv0, ino->u.smbfs_i.fileid);
680 WSET(server->packet, smb_vwv1, count);
681 DSET(server->packet, smb_vwv2, offset);
682 WSET(server->packet, smb_vwv4, 0);
684 *p++ = 1;
685 WSET(p, 0, count);
686 memcpy(p+2, data, count);
688 if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0)
689 res = WVAL(server->packet, smb_vwv0);
691 smb_unlock_server(server);
693 return res;
697 smb_proc_create(struct dentry *dir, struct qstr *name,
698 __u16 attr, time_t ctime)
700 int error;
701 char *p;
702 struct inode *i=dir->d_inode;
703 struct smb_sb_info *server = SMB_SERVER(i);
704 char *buf;
706 smb_lock_server(server);
707 retry:
708 buf = server->packet;
709 p = smb_setup_header(server, SMBcreate, 3, 0);
710 WSET(buf, smb_vwv0, attr);
711 DSET(buf, smb_vwv1, utc2local(ctime));
712 *p++ = 4;
713 p = smb_encode_path(server, p, dir, name);
714 smb_setup_bcc(server, p);
716 if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0)
718 if (smb_retry(server))
720 goto retry;
722 smb_unlock_server(server);
723 return error;
725 smb_proc_close(server, WVAL(buf, smb_vwv0), CURRENT_TIME);
726 smb_unlock_server(server);
728 return 0;
732 smb_proc_mv(struct dentry *odir, struct qstr *oname,
733 struct dentry *ndir, struct qstr *nname)
735 char *p;
736 struct smb_sb_info *server = SMB_SERVER(odir->d_inode);
737 int result;
739 smb_lock_server(server);
741 retry:
742 p = smb_setup_header(server, SMBmv, 1, 0);
743 WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
744 *p++ = 4;
745 p = smb_encode_path(server, p, odir, oname);
746 *p++ = 4;
747 p = smb_encode_path(server, p, ndir, nname);
748 smb_setup_bcc(server, p);
750 if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0)
752 if (smb_retry(server))
754 goto retry;
757 smb_unlock_server(server);
758 return result;
762 smb_proc_mkdir(struct dentry *dir, struct qstr *name)
764 char *p;
765 int result;
766 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
768 smb_lock_server(server);
770 retry:
771 p = smb_setup_header(server, SMBmkdir, 0, 0);
772 *p++ = 4;
773 p = smb_encode_path(server, p, dir, name);
774 smb_setup_bcc(server, p);
776 if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0)
778 if (smb_retry(server))
780 goto retry;
783 smb_unlock_server(server);
784 return result;
788 smb_proc_rmdir(struct dentry *dir, struct qstr *name)
790 char *p;
791 int result;
792 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
794 smb_lock_server(server);
796 retry:
797 p = smb_setup_header(server, SMBrmdir, 0, 0);
798 *p++ = 4;
799 p = smb_encode_path(server, p, dir, name);
800 smb_setup_bcc(server, p);
802 if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0)
804 if (smb_retry(server))
806 goto retry;
809 smb_unlock_server(server);
810 return result;
814 smb_proc_unlink(struct dentry *dir, struct qstr *name)
816 char *p;
817 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
818 int result;
820 smb_lock_server(server);
822 retry:
823 p = smb_setup_header(server, SMBunlink, 1, 0);
824 WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
825 *p++ = 4;
826 p = smb_encode_path(server, p, dir, name);
827 smb_setup_bcc(server, p);
829 if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0)
831 if (smb_retry(server))
833 goto retry;
836 smb_unlock_server(server);
837 return result;
841 smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
843 char *p;
844 char *buf;
845 int result;
847 smb_lock_server(server);
849 retry:
850 buf = server->packet;
851 p = smb_setup_header(server, SMBwrite, 5, 0);
852 WSET(buf, smb_vwv0, fid);
853 WSET(buf, smb_vwv1, 0);
854 DSET(buf, smb_vwv2, length);
855 WSET(buf, smb_vwv4, 0);
856 *p++ = 4;
857 *p++ = 0;
858 smb_setup_bcc(server, p);
860 if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0)
862 if (smb_retry(server))
864 goto retry;
867 smb_unlock_server(server);
868 return result;
871 static void
872 smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
874 memset(fattr, 0, sizeof(*fattr));
876 fattr->f_nlink = 1;
877 fattr->f_uid = server->m.uid;
878 fattr->f_gid = server->m.gid;
879 fattr->f_blksize = 512;
882 static void
883 smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
885 if (fattr->attr & aDIR)
887 fattr->f_mode = server->m.dir_mode;
888 fattr->f_size = 512;
889 } else
891 fattr->f_mode = server->m.file_mode;
894 if ((fattr->f_blksize != 0) && (fattr->f_size != 0))
896 fattr->f_blocks =
897 (fattr->f_size - 1) / fattr->f_blksize + 1;
898 } else
900 fattr->f_blocks = 0;
902 return;
905 void
906 smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
908 smb_init_dirent(server, fattr);
909 fattr->attr = aDIR;
910 fattr->f_ino = 1;
911 smb_finish_dirent(server, fattr);
915 static __u8 *
916 smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
917 struct smb_dirent *entry)
919 smb_init_dirent(server, &(entry->attr));
921 p += SMB_STATUS_SIZE; /* reserved (search_status) */
922 entry->attr.attr = *p;
923 entry->attr.f_mtime = entry->attr.f_atime = entry->attr.f_ctime =
924 date_dos2unix(WVAL(p, 1), WVAL(p, 3));
925 entry->attr.f_size = DVAL(p, 5);
926 entry->len = strlen(p + 9);
927 if (entry->len > 12)
929 entry->len = 12;
931 memcpy(entry->name, p + 9, entry->len);
932 entry->name[entry->len] = '\0';
933 while (entry->len > 2)
935 /* Pathworks fills names with spaces */
936 entry->len -= 1;
937 if (entry->name[entry->len] == ' ')
939 entry->name[entry->len] = '\0';
942 switch (server->opt.case_handling)
944 case SMB_CASE_UPPER:
945 str_upper(entry->name);
946 break;
947 case SMB_CASE_LOWER:
948 str_lower(entry->name);
949 break;
950 default:
951 break;
953 pr_debug("smb_decode_dirent: name = %s\n", entry->name);
954 smb_finish_dirent(server, &(entry->attr));
955 return p + 22;
958 /* This routine is used to read in directory entries from the network.
959 Note that it is for short directory name seeks, i.e.: protocol <
960 SMB_PROTOCOL_LANMAN2 */
962 static int
963 smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos,
964 int cache_size, struct smb_dirent *entry)
966 char *p;
967 char *buf;
968 int error;
969 int result;
970 int i;
971 int first, total_count;
972 struct smb_dirent *current_entry;
973 __u16 bcc;
974 __u16 count;
975 char status[SMB_STATUS_SIZE];
976 int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE;
978 static struct qstr mask = { "*.*", 3, 0 };
980 pr_debug("SMB call readdir %d @ %d\n", cache_size, fpos);
982 smb_lock_server(server);
984 retry:
985 buf = server->packet;
986 first = 1;
987 total_count = 0;
988 current_entry = entry;
990 while (1)
992 if (first == 1)
994 p = smb_setup_header(server, SMBsearch, 2, 0);
995 WSET(buf, smb_vwv0, entries_asked);
996 WSET(buf, smb_vwv1, aDIR);
997 *p++ = 4;
998 p = smb_encode_path(server, p, dir, &mask);
999 *p++ = 5;
1000 WSET(p, 0, 0);
1001 p += 2;
1002 } else
1004 p = smb_setup_header(server, SMBsearch, 2, 0);
1005 WSET(buf, smb_vwv0, entries_asked);
1006 WSET(buf, smb_vwv1, aDIR);
1007 *p++ = 4;
1008 *p++ = 0;
1009 *p++ = 5;
1010 WSET(p, 0, SMB_STATUS_SIZE);
1011 p += 2;
1012 memcpy(p, status, SMB_STATUS_SIZE);
1013 p += SMB_STATUS_SIZE;
1016 smb_setup_bcc(server, p);
1018 if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0)
1020 if ((server->rcls == ERRDOS)
1021 && (server->err == ERRnofiles))
1023 result = total_count - fpos;
1024 goto unlock_return;
1025 } else
1027 if (smb_retry(server))
1029 goto retry;
1031 result = error;
1032 goto unlock_return;
1035 p = SMB_VWV(server->packet);
1036 count = WVAL(p, 0);
1037 bcc = WVAL(p, 2);
1039 first = 0;
1041 if (count <= 0)
1043 result = total_count - fpos;
1044 goto unlock_return;
1046 if (bcc != count * SMB_DIRINFO_SIZE + 3)
1048 result = -EIO;
1049 goto unlock_return;
1051 p += 7;
1053 /* Read the last entry into the status field. */
1054 memcpy(status,
1055 SMB_BUF(server->packet) + 3 +
1056 (count - 1) * SMB_DIRINFO_SIZE,
1057 SMB_STATUS_SIZE);
1059 /* Now we are ready to parse smb directory entries. */
1061 for (i = 0; i < count; i++)
1063 if (total_count < fpos)
1065 p += SMB_DIRINFO_SIZE;
1066 pr_debug("smb_proc_readdir: skipped entry.\n");
1067 pr_debug(" total_count = %d\n"
1068 " i = %d, fpos = %d\n",
1069 total_count, i, fpos);
1070 } else if (total_count >= fpos + cache_size)
1072 result = total_count - fpos;
1073 goto unlock_return;
1074 } else
1076 p = smb_decode_dirent(server, p,
1077 current_entry);
1078 current_entry->f_pos = total_count;
1079 pr_debug("smb_proc_readdir: entry->f_pos = "
1080 "%u\n", entry->f_pos);
1081 current_entry += 1;
1083 total_count += 1;
1086 unlock_return:
1087 smb_unlock_server(server);
1088 return result;
1091 /* interpret a long filename structure - this is mostly guesses at the
1092 moment. The length of the structure is returned. The structure of
1093 a long filename depends on the info level. 260 is used by NT and 2
1094 is used by OS/2. */
1096 static char *
1097 smb_decode_long_dirent(struct smb_sb_info *server, char *p,
1098 struct smb_dirent *entry, int level)
1100 char *result;
1102 smb_init_dirent(server, &(entry->attr));
1104 switch (level)
1106 /* We might add more levels later... */
1107 case 1:
1108 entry->len = *(p+26);
1109 strncpy(entry->name, p + 27, entry->len);
1110 entry->name[entry->len] = '\0';
1111 entry->attr.f_size = DVAL(p, 16);
1112 entry->attr.attr = *(p+24);
1114 entry->attr.f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
1115 entry->attr.f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
1116 entry->attr.f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12));
1117 result = p + 28 + *(p+26);
1118 break;
1120 default:
1121 pr_debug("Unknown long filename format %d\n", level);
1122 result = p + WVAL(p, 0);
1125 switch (server->opt.case_handling)
1127 case SMB_CASE_UPPER:
1128 str_upper(entry->name);
1129 break;
1130 case SMB_CASE_LOWER:
1131 str_lower(entry->name);
1132 break;
1133 default:
1134 break;
1137 smb_finish_dirent(server, &(entry->attr));
1138 return result;
1141 static int
1142 smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
1143 int cache_size, struct smb_dirent *cache)
1145 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1146 const int info_level = 1;
1147 const int max_matches = 512;
1149 char *p;
1150 char *lastname;
1151 int lastname_len;
1152 int i;
1153 int first, entries, entries_seen;
1155 unsigned char *resp_data = NULL;
1156 unsigned char *resp_param = NULL;
1157 int resp_data_len = 0;
1158 int resp_param_len = 0;
1160 __u16 command;
1162 int result;
1164 int ff_resume_key = 0;
1165 int ff_searchcount = 0;
1166 int ff_eos = 0;
1167 int ff_lastname = 0;
1168 int ff_dir_handle = 0;
1169 int loop_count = 0;
1171 char param[SMB_MAXPATHLEN + 2 + 12];
1172 int mask_len;
1173 char *mask = &(param[12]);
1175 static struct qstr star = { "*", 1, 0 };
1177 mask_len = smb_encode_path(server, mask, dir, &star) - mask;
1179 mask[mask_len] = 0;
1180 mask[mask_len + 1] = 0;
1182 pr_debug("smb_readdir_long cache=%d, fpos=%d, mask=%s\n",
1183 cache_size, fpos, mask);
1185 smb_lock_server(server);
1187 retry:
1189 first = 1;
1190 entries = 0;
1191 entries_seen = 2;
1193 while (ff_eos == 0)
1195 loop_count += 1;
1196 if (loop_count > 200)
1198 printk(KERN_WARNING "smb_proc_readdir_long: "
1199 "Looping in FIND_NEXT??\n");
1200 break;
1202 if (first != 0)
1204 command = TRANSACT2_FINDFIRST;
1205 WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
1206 WSET(param, 2, max_matches); /* max count */
1207 WSET(param, 4, 8 + 4 + 2); /* resume required +
1208 close on end +
1209 continue */
1210 WSET(param, 6, info_level);
1211 DSET(param, 8, 0);
1212 } else
1214 command = TRANSACT2_FINDNEXT;
1215 pr_debug("hand=0x%X resume=%d ff_lastnm=%d mask=%s\n",
1216 ff_dir_handle, ff_resume_key, ff_lastname,
1217 mask);
1218 WSET(param, 0, ff_dir_handle);
1219 WSET(param, 2, max_matches); /* max count */
1220 WSET(param, 4, info_level);
1221 DSET(param, 6, ff_resume_key); /* ff_resume_key */
1222 WSET(param, 10, 8 + 4 + 2); /* resume required +
1223 close on end +
1224 continue */
1225 #ifdef CONFIG_SMB_WIN95
1226 /* Windows 95 is not able to deliver answers
1227 to FIND_NEXT fast enough, so sleep 0.2 seconds */
1228 current->timeout = jiffies + HZ / 5;
1229 current->state = TASK_INTERRUPTIBLE;
1230 schedule();
1231 current->timeout = 0;
1232 #endif
1235 result = smb_trans2_request(server, command,
1236 0, NULL, 12 + mask_len + 2, param,
1237 &resp_data_len, &resp_data,
1238 &resp_param_len, &resp_param);
1240 if (result < 0)
1242 if (smb_retry(server))
1244 goto retry;
1246 pr_debug("smb_proc_readdir_long: "
1247 "got error from trans2_request\n");
1248 break;
1250 if (server->rcls != 0)
1252 result = -EIO;
1253 break;
1255 /* parse out some important return info */
1256 if (first != 0)
1258 ff_dir_handle = WVAL(resp_param, 0);
1259 ff_searchcount = WVAL(resp_param, 2);
1260 ff_eos = WVAL(resp_param, 4);
1261 ff_lastname = WVAL(resp_param, 8);
1262 } else
1264 ff_searchcount = WVAL(resp_param, 0);
1265 ff_eos = WVAL(resp_param, 2);
1266 ff_lastname = WVAL(resp_param, 6);
1269 if (ff_searchcount == 0)
1271 break;
1273 /* point to the data bytes */
1274 p = resp_data;
1276 /* we might need the lastname for continuations */
1277 lastname = "";
1278 lastname_len = 0;
1279 if (ff_lastname > 0)
1281 switch (info_level)
1283 case 260:
1284 lastname = p + ff_lastname;
1285 lastname_len = resp_data_len - ff_lastname;
1286 ff_resume_key = 0;
1287 break;
1288 case 1:
1289 lastname = p + ff_lastname + 1;
1290 lastname_len = *(p+ff_lastname);
1291 ff_resume_key = 0;
1292 break;
1295 lastname_len = min(lastname_len, 256);
1296 strncpy(mask, lastname, lastname_len);
1297 mask[lastname_len] = '\0';
1299 /* Now we are ready to parse smb directory entries. */
1301 for (i = 0; i < ff_searchcount; i++)
1303 struct smb_dirent *entry = &(cache[entries]);
1305 p = smb_decode_long_dirent(server, p,
1306 entry, info_level);
1308 pr_debug("smb_readdir_long: got %s\n", entry->name);
1310 if ((entry->name[0] == '.')
1311 && ((entry->name[1] == '\0')
1312 || ((entry->name[1] == '.')
1313 && (entry->name[2] == '\0'))))
1315 /* ignore . and .. from the server */
1316 continue;
1318 if (entries_seen >= fpos)
1320 entry->f_pos = entries_seen;
1321 entries += 1;
1323 if (entries >= cache_size)
1325 goto finished;
1327 entries_seen += 1;
1330 pr_debug("received %d entries (eos=%d resume=%d)\n",
1331 ff_searchcount, ff_eos, ff_resume_key);
1333 first = 0;
1336 finished:
1337 smb_unlock_server(server);
1338 return entries;
1342 smb_proc_readdir(struct dentry *dir, int fpos,
1343 int cache_size, struct smb_dirent *entry)
1345 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
1347 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
1348 return smb_proc_readdir_long(server, dir, fpos, cache_size,
1349 entry);
1350 else
1351 return smb_proc_readdir_short(server, dir, fpos, cache_size,
1352 entry);
1355 static int
1356 smb_proc_getattr_core(struct dentry *dir, struct qstr *name,
1357 struct smb_fattr *attr)
1359 int result;
1360 char *p;
1361 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
1362 char *buf;
1364 smb_lock_server(server);
1366 retry:
1367 buf = server->packet;
1368 p = smb_setup_header(server, SMBgetatr, 0, 0);
1369 *p++ = 4;
1370 p = smb_encode_path(server, p, dir, name);
1371 smb_setup_bcc(server, p);
1373 if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
1375 if (smb_retry(server))
1377 goto retry;
1379 smb_unlock_server(server);
1380 return result;
1382 attr->attr = WVAL(buf, smb_vwv0);
1383 attr->f_ctime = attr->f_atime =
1384 attr->f_mtime = local2utc(DVAL(buf, smb_vwv1));
1386 attr->f_size = DVAL(buf, smb_vwv3);
1387 smb_unlock_server(server);
1388 return 0;
1391 static int
1392 smb_proc_getattr_trans2(struct dentry *dir, struct qstr *name,
1393 struct smb_fattr *attr)
1395 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
1396 char param[SMB_MAXPATHLEN + 20];
1397 char *p;
1398 int result;
1400 unsigned char *resp_data = NULL;
1401 unsigned char *resp_param = NULL;
1402 int resp_data_len = 0;
1403 int resp_param_len = 0;
1405 WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
1406 DSET(param, 2, 0);
1407 p = smb_encode_path(server, param + 6, dir, name);
1409 smb_lock_server(server);
1410 retry:
1411 result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
1412 0, NULL, p - param, param,
1413 &resp_data_len, &resp_data,
1414 &resp_param_len, &resp_param);
1416 if (server->rcls != 0)
1418 smb_unlock_server(server);
1419 return -smb_errno(server->rcls, server->err);
1421 if (result < 0)
1423 if (smb_retry(server))
1425 goto retry;
1427 smb_unlock_server(server);
1428 return result;
1430 if (resp_data_len < 22)
1432 smb_unlock_server(server);
1433 return -ENOENT;
1435 attr->f_ctime = date_dos2unix(WVAL(resp_data, 2),
1436 WVAL(resp_data, 0));
1437 attr->f_atime = date_dos2unix(WVAL(resp_data, 6),
1438 WVAL(resp_data, 4));
1439 attr->f_mtime = date_dos2unix(WVAL(resp_data, 10),
1440 WVAL(resp_data, 8));
1441 attr->f_size = DVAL(resp_data, 12);
1442 attr->attr = WVAL(resp_data, 20);
1443 smb_unlock_server(server);
1445 return 0;
1448 int smb_proc_getattr(struct dentry *dir, struct qstr *name,
1449 struct smb_fattr *fattr)
1451 struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
1452 int result = 0;
1454 smb_init_dirent(server, fattr);
1456 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
1457 result = smb_proc_getattr_trans2(dir, name, fattr);
1459 if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
1460 result = smb_proc_getattr_core(dir, name, fattr);
1462 smb_finish_dirent(server, fattr);
1464 return result;
1468 /* In core protocol, there is only 1 time to be set, we use
1469 entry->f_mtime, to make touch work. */
1470 static int
1471 smb_proc_setattr_core(struct smb_sb_info *server,
1472 struct dentry *dir, struct smb_fattr *fattr)
1474 char *p;
1475 char *buf;
1476 int result;
1478 smb_lock_server(server);
1480 retry:
1481 buf = server->packet;
1482 p = smb_setup_header(server, SMBsetatr, 8, 0);
1483 WSET(buf, smb_vwv0, fattr->attr);
1484 DSET(buf, smb_vwv1, utc2local(fattr->f_mtime));
1485 *p++ = 4;
1486 p = smb_encode_path(server, p, dir, NULL);
1487 *p++ = 4;
1488 *p++ = 0;
1490 smb_setup_bcc(server, p);
1491 if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0)
1492 if (smb_retry(server))
1493 goto retry;
1495 smb_unlock_server(server);
1496 return result;
1499 static int
1500 smb_proc_setattr_trans2(struct smb_sb_info *server,
1501 struct dentry *dir, struct smb_fattr *fattr)
1503 char param[SMB_MAXPATHLEN + 20];
1504 char data[26];
1505 char *p;
1506 int result;
1508 unsigned char *resp_data = NULL;
1509 unsigned char *resp_param = NULL;
1510 int resp_data_len = 0;
1511 int resp_param_len = 0;
1513 WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
1514 DSET(param, 2, 0);
1515 p = smb_encode_path(server, param + 6, dir, NULL);
1517 date_unix2dos(fattr->f_ctime, &(data[0]), &(data[2]));
1518 date_unix2dos(fattr->f_atime, &(data[4]), &(data[6]));
1519 date_unix2dos(fattr->f_mtime, &(data[8]), &(data[10]));
1520 DSET(data, 12, fattr->f_size);
1521 DSET(data, 16, fattr->f_blksize);
1522 WSET(data, 20, fattr->attr);
1523 WSET(data, 22, 0);
1525 smb_lock_server(server);
1526 retry:
1527 result = smb_trans2_request(server, TRANSACT2_SETPATHINFO,
1528 26, data, p - param, param,
1529 &resp_data_len, &resp_data,
1530 &resp_param_len, &resp_param);
1532 if (server->rcls != 0)
1534 smb_unlock_server(server);
1535 return -smb_errno(server->rcls, server->err);
1537 if (result < 0)
1538 if (smb_retry(server))
1539 goto retry;
1541 smb_unlock_server(server);
1542 return 0;
1546 smb_proc_setattr(struct smb_sb_info *server, struct dentry *dir,
1547 struct smb_fattr *fattr)
1549 int result;
1551 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
1552 result = smb_proc_setattr_trans2(server, dir, fattr);
1554 if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
1555 result = smb_proc_setattr_core(server, dir, fattr);
1557 return result;
1561 smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
1563 int error;
1564 char *p;
1565 struct smb_sb_info *server = &(sb->u.smbfs_sb);
1567 smb_lock_server(server);
1569 retry:
1570 smb_setup_header(server, SMBdskattr, 0, 0);
1572 if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0)
1574 if (smb_retry(server))
1575 goto retry;
1577 smb_unlock_server(server);
1578 return error;
1580 p = SMB_VWV(server->packet);
1581 attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
1582 attr->f_blocks = WVAL(p, 0);
1583 attr->f_bavail = attr->f_bfree = WVAL(p, 6);
1584 smb_unlock_server(server);
1585 return 0;
1589 smb_proc_disconnect(struct smb_sb_info *server)
1591 int result;
1592 smb_lock_server(server);
1593 smb_setup_header(server, SMBtdis, 0, 0);
1594 result = smb_request_ok(server, SMBtdis, 0, 0);
1595 smb_unlock_server(server);
1596 return result;