[PATCH] smbfs LFS
[opensuse:kernel.git] / fs / smbfs / proc.c
1 /*
2  *  proc.c
3  *
4  *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5  *  Copyright (C) 1997 by Volker Lendecke
6  *
7  *  Please add a note about your changes to smbfs in the ChangeLog file.
8  */
9
10 #include <linux/types.h>
11 #include <linux/errno.h>
12 #include <linux/slab.h>
13 #include <linux/fs.h>
14 #include <linux/file.h>
15 #include <linux/stat.h>
16 #include <linux/fcntl.h>
17 #include <linux/dcache.h>
18 #include <linux/dirent.h>
19 #include <linux/nls.h>
20
21 #include <linux/smb_fs.h>
22 #include <linux/smbno.h>
23 #include <linux/smb_mount.h>
24
25 #include <asm/string.h>
26 #include <asm/div64.h>
27
28 #include "smb_debug.h"
29 #include "proto.h"
30
31
32 /* Features. Undefine if they cause problems, this should perhaps be a
33    config option. */
34 #define SMBFS_POSIX_UNLINK 1
35
36 /* Allow smb_retry to be interrupted. */
37 #define SMB_RETRY_INTR
38
39 #define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
40 #define SMB_CMD(packet)  (*(packet+8))
41 #define SMB_WCT(packet)  (*(packet+SMB_HEADER_LEN - 1))
42 #define SMB_BCC(packet)  smb_bcc(packet)
43 #define SMB_BUF(packet)  ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
44
45 #define SMB_DIRINFO_SIZE 43
46 #define SMB_STATUS_SIZE  21
47
48 #define SMB_ST_BLKSIZE  (PAGE_SIZE)
49 #define SMB_ST_BLKSHIFT (PAGE_SHIFT)
50
51 static struct smb_ops smb_ops_core;
52 static struct smb_ops smb_ops_os2;
53 static struct smb_ops smb_ops_win95;
54 static struct smb_ops smb_ops_winNT;
55
56 static void
57 smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
58 static void
59 smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
60 static int
61 smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
62                       struct smb_fattr *fattr);
63 static int
64 smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
65                     struct smb_fattr *fattr);
66 static int
67 smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
68                       u16 attr);
69 static int
70 smb_proc_setattr_ext(struct smb_sb_info *server,
71                      struct inode *inode, struct smb_fattr *fattr);
72 static void
73 install_ops(struct smb_ops *dst, struct smb_ops *src);
74
75
76 static void
77 str_upper(char *name, int len)
78 {
79         while (len--)
80         {
81                 if (*name >= 'a' && *name <= 'z')
82                         *name -= ('a' - 'A');
83                 name++;
84         }
85 }
86
87 #if 0
88 static void
89 str_lower(char *name, int len)
90 {
91         while (len--)
92         {
93                 if (*name >= 'A' && *name <= 'Z')
94                         *name += ('a' - 'A');
95                 name++;
96         }
97 }
98 #endif
99
100 /* reverse a string inline. This is used by the dircache walking routines */
101 static void reverse_string(char *buf, int len)
102 {
103         char c;
104         char *end = buf+len-1;
105
106         while(buf < end) {
107                 c = *buf;
108                 *(buf++) = *end;
109                 *(end--) = c;
110         }
111 }
112
113 /* no conversion, just a wrapper for memcpy. */
114 static int convert_memcpy(char *output, int olen,
115                           const char *input, int ilen,
116                           struct nls_table *nls_from,
117                           struct nls_table *nls_to)
118 {
119         if (olen < ilen)
120                 return -ENAMETOOLONG;
121         memcpy(output, input, ilen);
122         return ilen;
123 }
124
125 static inline int write_char(unsigned char ch, char *output, int olen)
126 {
127         if (olen < 4)
128                 return -ENAMETOOLONG;
129         sprintf(output, ":x%02x", ch);
130         return 4;
131 }
132
133 static inline int write_unichar(wchar_t ch, char *output, int olen)
134 {
135         if (olen < 5)
136                 return -ENAMETOOLONG;
137         sprintf(output, ":%04x", ch);
138         return 5;
139 }
140
141 /* convert from one "codepage" to another (possibly being utf8). */
142 static int convert_cp(char *output, int olen,
143                       const char *input, int ilen,
144                       struct nls_table *nls_from,
145                       struct nls_table *nls_to)
146 {
147         int len = 0;
148         int n;
149         wchar_t ch;
150
151         while (ilen > 0) {
152                 /* convert by changing to unicode and back to the new cp */
153                 n = nls_from->char2uni((unsigned char *)input, ilen, &ch);
154                 if (n == -EINVAL) {
155                         ilen--;
156                         n = write_char(*input++, output, olen);
157                         if (n < 0)
158                                 goto fail;
159                         output += n;
160                         olen -= n;
161                         len += n;
162                         continue;
163                 } else if (n < 0)
164                         goto fail;
165                 input += n;
166                 ilen -= n;
167
168                 n = nls_to->uni2char(ch, output, olen);
169                 if (n == -EINVAL)
170                         n = write_unichar(ch, output, olen);
171                 if (n < 0)
172                         goto fail;
173                 output += n;
174                 olen -= n;
175
176                 len += n;
177         }
178         return len;
179 fail:
180         return n;
181 }
182
183 static int setcodepage(struct nls_table **p, char *name)
184 {
185         struct nls_table *nls;
186
187         if (!name || !*name) {
188                 nls = NULL;
189         } else if ( (nls = load_nls(name)) == NULL) {
190                 printk (KERN_ERR "smbfs: failed to load nls '%s'\n", name);
191                 return -EINVAL;
192         }
193
194         /* if already set, unload the previous one. */
195         if (*p)
196                 unload_nls(*p);
197         *p = nls;
198
199         return 0;
200 }
201
202 /* Handles all changes to codepage settings. */
203 int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
204 {
205         int n = 0;
206
207         smb_lock_server(server);
208
209         /* Don't load any nls_* at all, if no remote is requested */
210         if (!*cp->remote_name)
211                 goto out;
212
213         n = setcodepage(&server->local_nls, cp->local_name);
214         if (n != 0)
215                 goto out;
216         n = setcodepage(&server->remote_nls, cp->remote_name);
217         if (n != 0)
218                 setcodepage(&server->local_nls, NULL);
219
220 out:
221         if (server->local_nls != NULL && server->remote_nls != NULL)
222                 server->ops->convert = convert_cp;
223         else
224                 server->ops->convert = convert_memcpy;
225
226         smb_unlock_server(server);
227         return n;
228 }
229
230
231 /*****************************************************************************/
232 /*                                                                           */
233 /*  Encoding/Decoding section                                                */
234 /*                                                                           */
235 /*****************************************************************************/
236
237 static __u8 *
238 smb_encode_smb_length(__u8 * p, __u32 len)
239 {
240         *p = 0;
241         *(p+1) = 0;
242         *(p+2) = (len & 0xFF00) >> 8;
243         *(p+3) = (len & 0xFF);
244         if (len > 0xFFFF)
245         {
246                 *(p+1) = 1;
247         }
248         return p + 4;
249 }
250
251 /*
252  * smb_build_path: build the path to entry and name storing it in buf.
253  * The path returned will have the trailing '\0'.
254  */
255 static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen,
256                           struct dentry * entry, struct qstr * name)
257 {
258         char *path = buf;
259         int len;
260
261         if (maxlen < 2)
262                 return -ENAMETOOLONG;
263
264         if (maxlen > SMB_MAXPATHLEN + 1)
265                 maxlen = SMB_MAXPATHLEN + 1;
266
267         if (entry == NULL)
268                 goto test_name_and_out;
269
270         /*
271          * If IS_ROOT, we have to do no walking at all.
272          */
273         if (IS_ROOT(entry) && !name) {
274                 *path++ = '\\';
275                 *path++ = '\0';
276                 return 2;
277         }
278
279         /*
280          * Build the path string walking the tree backward from end to ROOT
281          * and store it in reversed order [see reverse_string()]
282          */
283         read_lock(&dparent_lock);
284         while (!IS_ROOT(entry)) {
285                 if (maxlen < 3) {
286                         read_unlock(&dparent_lock);
287                         return -ENAMETOOLONG;
288                 }
289
290                 len = server->ops->convert(path, maxlen-2, 
291                                       entry->d_name.name, entry->d_name.len,
292                                       server->local_nls, server->remote_nls);
293                 if (len < 0) {
294                         read_unlock(&dparent_lock);
295                         return len;
296                 }
297                 reverse_string(path, len);
298                 path += len;
299                 *path++ = '\\';
300                 maxlen -= len+1;
301
302                 entry = entry->d_parent;
303                 if (IS_ROOT(entry))
304                         break;
305         }
306         read_unlock(&dparent_lock);
307         reverse_string(buf, path-buf);
308
309         /* maxlen is at least 1 */
310 test_name_and_out:
311         if (name) {
312                 if (maxlen < 3)
313                         return -ENAMETOOLONG;
314                 *path++ = '\\';
315                 len = server->ops->convert(path, maxlen-2, 
316                                       name->name, name->len,
317                                       server->local_nls, server->remote_nls);
318                 if (len < 0)
319                         return len;
320                 path += len;
321                 maxlen -= len+1;
322         }
323         /* maxlen is at least 1 */
324         *path++ = '\0';
325         return path-buf;
326 }
327
328 static int smb_encode_path(struct smb_sb_info *server, char *buf, int maxlen,
329                            struct dentry *dir, struct qstr *name)
330 {
331         int result;
332
333         result = smb_build_path(server, buf, maxlen, dir, name);
334         if (result < 0)
335                 goto out;
336         if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
337                 str_upper(buf, result);
338 out:
339         return result;
340 }
341
342 static int smb_simple_encode_path(struct smb_sb_info *server, char **p,
343                           struct dentry * entry, struct qstr * name)
344 {
345         char *s = *p;
346         int res;
347         int maxlen = ((char *)server->packet + server->packet_size) - s;
348
349         if (!maxlen)
350                 return -ENAMETOOLONG;
351         *s++ = 4;
352         res = smb_encode_path(server, s, maxlen-1, entry, name);
353         if (res < 0)
354                 return res;
355         *p = s + res;
356         return 0;
357 }
358
359 /* The following are taken directly from msdos-fs */
360
361 /* Linear day numbers of the respective 1sts in non-leap years. */
362
363 static int day_n[] =
364 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
365                   /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
366
367
368 static time_t
369 utc2local(struct smb_sb_info *server, time_t time)
370 {
371         return time - server->opt.serverzone*60;
372 }
373
374 static time_t
375 local2utc(struct smb_sb_info *server, time_t time)
376 {
377         return time + server->opt.serverzone*60;
378 }
379
380 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
381
382 static time_t
383 date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
384 {
385         int month, year;
386         time_t secs;
387
388         /* first subtract and mask after that... Otherwise, if
389            date == 0, bad things happen */
390         month = ((date >> 5) - 1) & 15;
391         year = date >> 9;
392         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
393             ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
394                                                    month < 2 ? 1 : 0) + 3653);
395         /* days since 1.1.70 plus 80's leap day */
396         return local2utc(server, secs);
397 }
398
399
400 /* Convert linear UNIX date to a MS-DOS time/date pair. */
401
402 static void
403 date_unix2dos(struct smb_sb_info *server,
404               int unix_date, __u16 *date, __u16 *time)
405 {
406         int day, year, nl_day, month;
407
408         unix_date = utc2local(server, unix_date);
409         if (unix_date < 315532800)
410                 unix_date = 315532800;
411
412         *time = (unix_date % 60) / 2 +
413                 (((unix_date / 60) % 60) << 5) +
414                 (((unix_date / 3600) % 24) << 11);
415
416         day = unix_date / 86400 - 3652;
417         year = day / 365;
418         if ((year + 3) / 4 + 365 * year > day)
419                 year--;
420         day -= (year + 3) / 4 + 365 * year;
421         if (day == 59 && !(year & 3)) {
422                 nl_day = day;
423                 month = 2;
424         } else {
425                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
426                 for (month = 0; month < 12; month++)
427                         if (day_n[month] > nl_day)
428                                 break;
429         }
430         *date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
431 }
432
433 /* The following are taken from fs/ntfs/util.c */
434
435 #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
436
437 /*
438  * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
439  * into Unix UTC (based 1970-01-01, in seconds).
440  */
441 static time_t
442 smb_ntutc2unixutc(u64 ntutc)
443 {
444         /* FIXME: what about the timezone difference? */
445         /* Subtract the NTFS time offset, then convert to 1s intervals. */
446         u64 t = ntutc - NTFS_TIME_OFFSET;
447         do_div(t, 10000000);
448         return (time_t)t;
449 }
450
451 #if 0
452 /* Convert the Unix UTC into NT time */
453 static u64
454 smb_unixutc2ntutc(struct smb_sb_info *server, time_t t)
455 {
456         /* Note: timezone conversion is probably wrong. */
457         return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET;
458 }
459 #endif
460
461
462 /*****************************************************************************/
463 /*                                                                           */
464 /*  Support section.                                                         */
465 /*                                                                           */
466 /*****************************************************************************/
467
468 __u32
469 smb_len(__u8 * p)
470 {
471         return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3);
472 }
473
474 static __u16
475 smb_bcc(__u8 * packet)
476 {
477         int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16);
478         return WVAL(packet, pos);
479 }
480
481 /* smb_valid_packet: We check if packet fulfills the basic
482    requirements of a smb packet */
483
484 static int
485 smb_valid_packet(__u8 * packet)
486 {
487         return (packet[4] == 0xff
488                 && packet[5] == 'S'
489                 && packet[6] == 'M'
490                 && packet[7] == 'B'
491                 && (smb_len(packet) + 4 == SMB_HEADER_LEN
492                     + SMB_WCT(packet) * 2 + SMB_BCC(packet)));
493 }
494
495 /* smb_verify: We check if we got the answer we expected, and if we
496    got enough data. If bcc == -1, we don't care. */
497
498 static int
499 smb_verify(__u8 * packet, int command, int wct, int bcc)
500 {
501         if (SMB_CMD(packet) != command)
502                 goto bad_command;
503         if (SMB_WCT(packet) < wct)
504                 goto bad_wct;
505         if (bcc != -1 && SMB_BCC(packet) < bcc)
506                 goto bad_bcc;
507         return 0;
508
509 bad_command:
510         printk(KERN_ERR "smb_verify: command=%x, SMB_CMD=%x??\n",
511                command, SMB_CMD(packet));
512         goto fail;
513 bad_wct:
514         printk(KERN_ERR "smb_verify: command=%x, wct=%d, SMB_WCT=%d??\n",
515                command, wct, SMB_WCT(packet));
516         goto fail;
517 bad_bcc:
518         printk(KERN_ERR "smb_verify: command=%x, bcc=%d, SMB_BCC=%d??\n",
519                command, bcc, SMB_BCC(packet));
520 fail:
521         return -EIO;
522 }
523
524 /*
525  * Returns the maximum read or write size for the "payload". Making all of the
526  * packet fit within the negotiated max_xmit size.
527  *
528  * N.B. Since this value is usually computed before locking the server,
529  * the server's packet size must never be decreased!
530  */
531 static inline int
532 smb_get_xmitsize(struct smb_sb_info *server, int overhead)
533 {
534         return server->opt.max_xmit - overhead;
535 }
536
537 /*
538  * Calculate the maximum read size
539  */
540 int
541 smb_get_rsize(struct smb_sb_info *server)
542 {
543         /* readX has 12 parameters, read has 5 */
544         int overhead = SMB_HEADER_LEN + 12 * sizeof(__u16) + 2 + 1 + 2;
545         int size = smb_get_xmitsize(server, overhead);
546
547         VERBOSE("packet=%d, xmit=%d, size=%d\n",
548                 server->packet_size, server->opt.max_xmit, size);
549
550         return size;
551 }
552
553 /*
554  * Calculate the maximum write size
555  */
556 int
557 smb_get_wsize(struct smb_sb_info *server)
558 {
559         /* writeX has 14 parameters, write has 5 */
560         int overhead = SMB_HEADER_LEN + 14 * sizeof(__u16) + 2 + 1 + 2;
561         int size = smb_get_xmitsize(server, overhead);
562
563         VERBOSE("packet=%d, xmit=%d, size=%d\n",
564                 server->packet_size, server->opt.max_xmit, size);
565
566         return size;
567 }
568
569 /*
570  * Convert SMB error codes to -E... errno values.
571  */
572 int
573 smb_errno(struct smb_sb_info *server)
574 {
575         int errcls = server->rcls;
576         int error  = server->err;
577         char *class = "Unknown";
578
579         VERBOSE("errcls %d  code %d  from command 0x%x\n",
580                 errcls, error, SMB_CMD(server->packet));
581
582         if (errcls == ERRDOS) {
583                 switch (error) {
584                 case ERRbadfunc:
585                         return -EINVAL;
586                 case ERRbadfile:
587                 case ERRbadpath:
588                         return -ENOENT;
589                 case ERRnofids:
590                         return -EMFILE;
591                 case ERRnoaccess:
592                         return -EACCES;
593                 case ERRbadfid:
594                         return -EBADF;
595                 case ERRbadmcb:
596                         return -EREMOTEIO;
597                 case ERRnomem:
598                         return -ENOMEM;
599                 case ERRbadmem:
600                         return -EFAULT;
601                 case ERRbadenv:
602                 case ERRbadformat:
603                         return -EREMOTEIO;
604                 case ERRbadaccess:
605                         return -EACCES;
606                 case ERRbaddata:
607                         return -E2BIG;
608                 case ERRbaddrive:
609                         return -ENXIO;
610                 case ERRremcd:
611                         return -EREMOTEIO;
612                 case ERRdiffdevice:
613                         return -EXDEV;
614                 case ERRnofiles:
615                         return -ENOENT;
616                 case ERRbadshare:
617                         return -ETXTBSY;
618                 case ERRlock:
619                         return -EDEADLK;
620                 case ERRfilexists:
621                         return -EEXIST;
622                 case ERROR_INVALID_PARAMETER:
623                         return -EINVAL;
624                 case ERROR_DISK_FULL:
625                         return -ENOSPC;
626                 case ERROR_INVALID_NAME:
627                         return -ENOENT;
628                 case ERROR_DIR_NOT_EMPTY:
629                         return -ENOTEMPTY;
630                 case ERROR_NOT_LOCKED:
631                        return -ENOLCK;
632                 case ERROR_ALREADY_EXISTS:
633                         return -EEXIST;
634                 default:
635                         class = "ERRDOS";
636                         goto err_unknown;
637                 }
638         } else if (errcls == ERRSRV) {
639                 switch (error) {
640                 /* N.B. This is wrong ... EIO ? */
641                 case ERRerror:
642                         return -ENFILE;
643                 case ERRbadpw:
644                         return -EINVAL;
645                 case ERRbadtype:
646                         return -EIO;
647                 case ERRaccess:
648                         return -EACCES;
649                 /*
650                  * This is a fatal error, as it means the "tree ID"
651                  * for this connection is no longer valid. We map
652                  * to a special error code and get a new connection.
653                  */
654                 case ERRinvnid:
655                         return -EBADSLT;
656                 default:
657                         class = "ERRSRV";
658                         goto err_unknown;
659                 }
660         } else if (errcls == ERRHRD) {
661                 switch (error) {
662                 case ERRnowrite:
663                         return -EROFS;
664                 case ERRbadunit:
665                         return -ENODEV;
666                 case ERRnotready:
667                         return -EUCLEAN;
668                 case ERRbadcmd:
669                 case ERRdata:
670                         return -EIO;
671                 case ERRbadreq:
672                         return -ERANGE;
673                 case ERRbadshare:
674                         return -ETXTBSY;
675                 case ERRlock:
676                         return -EDEADLK;
677                 case ERRdiskfull:
678                         return -ENOSPC;
679                 default:
680                         class = "ERRHRD";
681                         goto err_unknown;
682                 }
683         } else if (errcls == ERRCMD) {
684                 class = "ERRCMD";
685         } else if (errcls == SUCCESS) {
686                 return 0;       /* This is the only valid 0 return */
687         }
688
689 err_unknown:
690         printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",
691                class, error, SMB_CMD(server->packet));
692         return -EIO;
693 }
694
695 /*
696  * smb_retry: This function should be called when smb_request_ok has
697  * indicated an error. If the error was indicated because the
698  * connection was killed, we try to reconnect. If smb_retry returns 0,
699  * the error was indicated for another reason, so a retry would not be
700  * of any use.
701  * N.B. The server must be locked for this call.
702  */
703 static int
704 smb_retry(struct smb_sb_info *server)
705 {
706         pid_t pid = server->conn_pid;
707         int error, result = 0;
708
709         if (server->state == CONN_VALID || server->state == CONN_RETRYING)
710                 goto out;
711
712         smb_close_socket(server);
713
714         if (pid == 0) {
715                 printk(KERN_ERR "smb_retry: no connection process\n");
716                 server->state = CONN_RETRIED;
717                 goto out;
718         }
719
720         /*
721          * Change state so that only one retry per server will be started.
722          */
723         server->state = CONN_RETRYING;
724
725         /*
726          * Note: use the "priv" flag, as a user process may need to reconnect.
727          */
728         error = kill_proc(pid, SIGUSR1, 1);
729         if (error) {
730                 /* FIXME: this is fatal */
731                 printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
732                 goto out;
733         }
734         VERBOSE("signalled pid %d, waiting for new connection\n", pid);
735
736         /*
737          * Wait for the new connection.
738          */
739 #ifdef SMB_RETRY_INTR
740         smb_unlock_server(server);
741         interruptible_sleep_on_timeout(&server->wait,  30*HZ);
742         smb_lock_server(server);
743         if (signal_pending(current))
744                 printk(KERN_INFO "smb_retry: caught signal\n");
745 #else
746         /*
747          * We don't want to be interrupted. For example, what if 'current'
748          * already has received a signal? sleep_on would terminate immediately
749          * and smbmount would not be able to re-establish connection.
750          *
751          * smbmount should be able to reconnect later, but it can't because
752          * it will get an -EIO on attempts to open the mountpoint!
753          *
754          * FIXME: go back to the interruptable version now that smbmount
755          * can avoid -EIO on the mountpoint when reconnecting?
756          */
757         smb_unlock_server(server);
758         sleep_on_timeout(&server->wait, 30*HZ);
759         smb_lock_server(server);
760 #endif
761
762         /*
763          * Check for a valid connection.
764          */
765         if (server->state == CONN_VALID) {
766                 /* This should be changed to VERBOSE, except many smbfs
767                    problems is with the userspace daemon not reconnecting. */
768                 PARANOIA("successful, new pid=%d, generation=%d\n",
769                          server->conn_pid, server->generation);
770                 result = 1;
771         } else if (server->state == CONN_RETRYING) {
772                 /* allow further attempts later */
773                 server->state = CONN_RETRIED;
774         }
775
776 out:
777         return result;
778 }
779
780 /* smb_request_ok: We expect the server to be locked. Then we do the
781    request and check the answer completely. When smb_request_ok
782    returns 0, you can be quite sure that everything went well. When
783    the answer is <=0, the returned number is a valid unix errno. */
784
785 static int
786 smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
787 {
788         int result = -EIO;
789
790         s->rcls = 0;
791         s->err = 0;
792
793         /* Make sure we have a connection */
794         if (s->state != CONN_VALID) {
795                 if (!smb_retry(s))
796                         goto out;
797         }
798
799         if (smb_request(s) < 0) {
800                 DEBUG1("smb_request failed\n");
801                 goto out;
802         }
803         if (smb_valid_packet(s->packet) != 0) {
804                 PARANOIA("invalid packet!\n");
805                 goto out;
806         }
807
808         /*
809          * Check for server errors.
810          */
811         if (s->rcls != 0) {
812                 result = smb_errno(s);
813                 if (!result)
814                         printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
815                                 s->rcls, s->err);
816                 /*
817                  * Exit now even if the error was squashed ...
818                  * packet verify will fail anyway.
819                  */
820                 goto out;
821         }
822         result = smb_verify(s->packet, command, wct, bcc);
823
824 out:
825         return result;
826 }
827
828 /*
829  * This implements the NEWCONN ioctl. It installs the server pid,
830  * sets server->state to CONN_VALID, and wakes up the waiting process.
831  */
832 int
833 smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
834 {
835         struct file *filp;
836         int error;
837
838         VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
839
840         smb_lock_server(server);
841
842         /*
843          * Make sure we don't already have a valid connection ...
844          */
845         error = -EINVAL;
846         if (server->state == CONN_VALID)
847                 goto out;
848
849         error = -EACCES;
850         if (current->uid != server->mnt->mounted_uid && 
851             !capable(CAP_SYS_ADMIN))
852                 goto out;
853
854         error = -EBADF;
855         filp = fget(opt->fd);
856         if (!filp)
857                 goto out;
858         if (!smb_valid_socket(filp->f_dentry->d_inode))
859                 goto out_putf;
860
861         server->sock_file = filp;
862         server->conn_pid = current->pid;
863         smb_catch_keepalive(server);
864         server->opt = *opt;
865         server->generation += 1;
866         server->state = CONN_VALID;
867         error = 0;
868
869         /* check if we have an old smbmount that uses seconds for the 
870            serverzone */
871         if (server->opt.serverzone > 12*60 || server->opt.serverzone < -12*60)
872                 server->opt.serverzone /= 60;
873
874         /* now that we have an established connection we can detect the server
875            type and enable bug workarounds */
876         if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
877                 install_ops(server->ops, &smb_ops_core);
878         else if (server->opt.protocol == SMB_PROTOCOL_LANMAN2)
879                 install_ops(server->ops, &smb_ops_os2);
880         else if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
881                  (server->opt.max_xmit < 0x1000) &&
882                  !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
883                 /* FIXME: can we kill the WIN95 flag now? */
884                 server->mnt->flags |= SMB_MOUNT_WIN95;
885                 VERBOSE("detected WIN95 server\n");
886                 install_ops(server->ops, &smb_ops_win95);
887         } else {
888                 /*
889                  * Samba has max_xmit 65535
890                  * NT4spX has max_xmit 4536 (or something like that)
891                  * win2k has ...
892                  */
893                 VERBOSE("detected NT1 (Samba, NT4/5) server\n");
894                 install_ops(server->ops, &smb_ops_winNT);
895         }
896
897         /* FIXME: the win9x code wants to modify these ... (seek/trunc bug) */
898         if (server->mnt->flags & SMB_MOUNT_OLDATTR) {
899                 server->ops->getattr = smb_proc_getattr_core;
900         } else if (server->mnt->flags & SMB_MOUNT_DIRATTR) {
901                 server->ops->getattr = smb_proc_getattr_ff;
902         }
903
904         /* Decode server capabilities */
905         if (server->opt.capabilities & SMB_CAP_LARGE_FILES) {
906                 /* Should be ok to set this now, as no one can access the
907                    mount until the connection has been established. */
908                 SB_of(server)->s_maxbytes = ~0ULL >> 1;
909                 VERBOSE("LFS enabled\n");
910         }
911 #if 0
912         /* flags we will test for other patches ... */
913         if (server->opt.capabilities & SMB_CAP_UNICODE) {
914                 VERBOSE("Unicode enabled\n");
915         }
916         if (server->opt.capabilities & SMB_CAP_LARGE_READX) {
917                 VERBOSE("Large reads enabled\n");
918         }
919         if (server->opt.capabilities & SMB_CAP_LARGE_WRITEX) {
920                 VERBOSE("Large writes enabled\n");
921         }
922 #endif
923
924         VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
925                 server->opt.protocol, server->opt.max_xmit, server->conn_pid,
926                 server->opt.capabilities);
927
928         /* Make sure we can fit a message of the negotiated size in our
929            packet buffer. */
930         if (server->opt.max_xmit > server->packet_size) {
931                 int len = smb_round_length(server->opt.max_xmit);
932                 char *buf = smb_vmalloc(len);
933                 if (buf) {
934                         if (server->packet)
935                                 smb_vfree(server->packet);
936                         server->packet = buf;
937                         server->packet_size = len;
938                 } else {
939                         /* else continue with the too small buffer? */
940                         PARANOIA("Failed to allocate new packet buffer: "
941                                  "max_xmit=%d, packet_size=%d\n",
942                                  server->opt.max_xmit, server->packet_size);
943                         server->opt.max_xmit = server->packet_size;
944                 }
945         }
946
947 out:
948         smb_unlock_server(server);
949         smb_wakeup(server);
950         return error;
951
952 out_putf:
953         fput(filp);
954         goto out;
955 }
956
957 int
958 smb_wakeup(struct smb_sb_info *server)
959 {
960 #ifdef SMB_RETRY_INTR
961         wake_up_interruptible(&server->wait);
962 #else
963         wake_up(&server->wait);
964 #endif
965         return 0;
966 }
967
968 /* smb_setup_header: We completely set up the packet. You only have to
969    insert the command-specific fields */
970
971 __u8 *
972 smb_setup_header(struct smb_sb_info * server, __u8 command, __u16 wct, __u16 bcc)
973 {
974         __u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2;
975         __u8 *p = server->packet;
976         __u8 *buf = server->packet;
977
978         if (xmit_len > server->packet_size)
979                 printk(KERN_DEBUG "smb_setup_header: "
980                        "Aieee, xmit len > packet! len=%d, size=%d\n",
981                        xmit_len, server->packet_size);
982
983         p = smb_encode_smb_length(p, xmit_len - 4);
984
985         *p++ = 0xff;
986         *p++ = 'S';
987         *p++ = 'M';
988         *p++ = 'B';
989         *p++ = command;
990
991         memset(p, '\0', 19);
992         p += 19;
993         p += 8;
994
995         WSET(buf, smb_tid, server->opt.tid);
996         WSET(buf, smb_pid, 1);
997         WSET(buf, smb_uid, server->opt.server_uid);
998         WSET(buf, smb_mid, 1);
999
1000         if (server->opt.protocol > SMB_PROTOCOL_CORE)
1001         {
1002                 *(buf+smb_flg) = 0x8;
1003                 WSET(buf, smb_flg2, 0x3);
1004         }
1005         *p++ = wct;             /* wct */
1006         p += 2 * wct;
1007         WSET(p, 0, bcc);
1008         return p + 2;
1009 }
1010
1011 static void
1012 smb_setup_bcc(struct smb_sb_info *server, __u8 * p)
1013 {
1014         __u8 *packet = server->packet;
1015         __u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet);
1016         __u16 bcc = p - (pbcc + 2);
1017
1018         WSET(pbcc, 0, bcc);
1019         smb_encode_smb_length(packet,
1020                               SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc);
1021 }
1022
1023 /*
1024  * Called with the server locked
1025  */
1026 static int
1027 smb_proc_seek(struct smb_sb_info *server, __u16 fileid,
1028               __u16 mode, off_t offset)
1029 {
1030         int result;
1031
1032         smb_setup_header(server, SMBlseek, 4, 0);
1033         WSET(server->packet, smb_vwv0, fileid);
1034         WSET(server->packet, smb_vwv1, mode);
1035         DSET(server->packet, smb_vwv2, offset);
1036
1037         result = smb_request_ok(server, SMBlseek, 2, 0);
1038         if (result < 0) {
1039                 result = 0;
1040                 goto out;
1041         }
1042
1043         result = DVAL(server->packet, smb_vwv0);
1044 out:
1045         return result;
1046 }
1047
1048 /*
1049  * We're called with the server locked, and we leave it that way.
1050  */
1051 static int
1052 smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
1053 {
1054         struct inode *ino = dentry->d_inode;
1055         struct smb_inode_info *ei = SMB_I(ino);
1056         int mode, read_write = 0x42, read_only = 0x40;
1057         int res;
1058         char *p;
1059
1060         /*
1061          * Attempt to open r/w, unless there are no write privileges.
1062          */
1063         mode = read_write;
1064         if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1065                 mode = read_only;
1066 #if 0
1067         /* FIXME: why is this code not in? below we fix it so that a caller
1068            wanting RO doesn't get RW. smb_revalidate_inode does some 
1069            optimization based on access mode. tail -f needs it to be correct.
1070
1071            We must open rw since we don't do the open if called a second time
1072            with different 'wish'. Is that not supported by smb servers? */
1073         if (!(wish & (O_WRONLY | O_RDWR)))
1074                 mode = read_only;
1075 #endif
1076
1077       retry:
1078         p = smb_setup_header(server, SMBopen, 2, 0);
1079         WSET(server->packet, smb_vwv0, mode);
1080         WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
1081         res = smb_simple_encode_path(server, &p, dentry, NULL);
1082         if (res < 0)
1083                 goto out;
1084         smb_setup_bcc(server, p);
1085
1086         res = smb_request_ok(server, SMBopen, 7, 0);
1087         if (res != 0) {
1088                 if (smb_retry(server))
1089                         goto retry;
1090
1091                 if (mode == read_write &&
1092                     (res == -EACCES || res == -ETXTBSY || res == -EROFS))
1093                 {
1094                         VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
1095                                 DENTRY_PATH(dentry), res);
1096                         mode = read_only;
1097                         goto retry;
1098                 }
1099                 goto out;
1100         }
1101         /* We should now have data in vwv[0..6]. */
1102
1103         ei->fileid = WVAL(server->packet, smb_vwv0);
1104         ei->attr   = WVAL(server->packet, smb_vwv1);
1105         /* smb_vwv2 has mtime */
1106         /* smb_vwv4 has size  */
1107         ei->access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
1108         ei->open = server->generation;
1109
1110 out:
1111         return res;
1112 }
1113
1114 /*
1115  * Make sure the file is open, and check that the access
1116  * is compatible with the desired access.
1117  */
1118 int
1119 smb_open(struct dentry *dentry, int wish)
1120 {
1121         struct inode *inode = dentry->d_inode;
1122         int result;
1123         __u16 access;
1124
1125         result = -ENOENT;
1126         if (!inode) {
1127                 printk(KERN_ERR "smb_open: no inode for dentry %s/%s\n",
1128                        DENTRY_PATH(dentry));
1129                 goto out;
1130         }
1131
1132         if (!smb_is_open(inode)) {
1133                 struct smb_sb_info *server = server_from_inode(inode);
1134                 smb_lock_server(server);
1135                 result = 0;
1136                 if (!smb_is_open(inode))
1137                         result = smb_proc_open(server, dentry, wish);
1138                 smb_unlock_server(server);
1139                 if (result) {
1140                         PARANOIA("%s/%s open failed, result=%d\n",
1141                                  DENTRY_PATH(dentry), result);
1142                         goto out;
1143                 }
1144                 /*
1145                  * A successful open means the path is still valid ...
1146                  */
1147                 smb_renew_times(dentry);
1148         }
1149
1150         /*
1151          * Check whether the access is compatible with the desired mode.
1152          */
1153         result = 0;
1154         access = SMB_I(inode)->access;
1155         if (access != wish && access != SMB_O_RDWR) {
1156                 PARANOIA("%s/%s access denied, access=%x, wish=%x\n",
1157                          DENTRY_PATH(dentry), access, wish);
1158                 result = -EACCES;
1159         }
1160 out:
1161         return result;
1162 }
1163
1164 /* We're called with the server locked */
1165
1166 static int 
1167 smb_proc_close(struct smb_sb_info *server, __u16 fileid, __u32 mtime)
1168 {
1169         smb_setup_header(server, SMBclose, 3, 0);
1170         WSET(server->packet, smb_vwv0, fileid);
1171         DSET(server->packet, smb_vwv1, utc2local(server, mtime));
1172         return smb_request_ok(server, SMBclose, 0, 0);
1173 }
1174
1175 /*
1176  * Called with the server locked.
1177  *
1178  * Win NT 4.0 has an apparent bug in that it fails to update the
1179  * modify time when writing to a file. As a workaround, we update
1180  * both modify and access time locally, and post the times to the
1181  * server when closing the file.
1182  */
1183 static int 
1184 smb_proc_close_inode(struct smb_sb_info *server, struct inode * ino)
1185 {
1186         struct smb_inode_info *ei = SMB_I(ino);
1187         int result = 0;
1188         if (smb_is_open(ino))
1189         {
1190                 /*
1191                  * We clear the open flag in advance, in case another
1192                  * process observes the value while we block below.
1193                  */
1194                 ei->open = 0;
1195
1196                 /*
1197                  * Kludge alert: SMB timestamps are accurate only to
1198                  * two seconds ... round the times to avoid needless
1199                  * cache invalidations!
1200                  */
1201                 if (ino->i_mtime & 1)
1202                         ino->i_mtime--;
1203                 if (ino->i_atime & 1)
1204                         ino->i_atime--;
1205                 /*
1206                  * If the file is open with write permissions,
1207                  * update the time stamps to sync mtime and atime.
1208                  */
1209                 if ((server->opt.protocol >= SMB_PROTOCOL_LANMAN2) &&
1210                     !(ei->access == SMB_O_RDONLY))
1211                 {
1212                         struct smb_fattr fattr;
1213                         smb_get_inode_attr(ino, &fattr);
1214                         smb_proc_setattr_ext(server, ino, &fattr);
1215                 }
1216
1217                 result = smb_proc_close(server, ei->fileid, ino->i_mtime);
1218                 /*
1219                  * Force a revalidation after closing ... some servers
1220                  * don't post the size until the file has been closed.
1221                  */
1222                 if (server->opt.protocol < SMB_PROTOCOL_NT1)
1223                         ei->oldmtime = 0;
1224                 ei->closed = jiffies;
1225         }
1226         return result;
1227 }
1228
1229 int
1230 smb_close(struct inode *ino)
1231 {
1232         int result = 0;
1233
1234         if (smb_is_open(ino)) {
1235                 struct smb_sb_info *server = server_from_inode(ino);
1236                 smb_lock_server(server);
1237                 result = smb_proc_close_inode(server, ino);
1238                 smb_unlock_server(server);
1239         }
1240         return result;
1241 }
1242
1243 /*
1244  * This is used to close a file following a failed instantiate.
1245  * Since we don't have an inode, we can't use any of the above.
1246  */
1247 int
1248 smb_close_fileid(struct dentry *dentry, __u16 fileid)
1249 {
1250         struct smb_sb_info *server = server_from_dentry(dentry);
1251         int result;
1252
1253         smb_lock_server(server);
1254         result = smb_proc_close(server, fileid, CURRENT_TIME);
1255         smb_unlock_server(server);
1256         return result;
1257 }
1258
1259 /* In smb_proc_read and smb_proc_write we do not retry, because the
1260    file-id would not be valid after a reconnection. */
1261
1262 static int
1263 smb_proc_read(struct inode *inode, loff_t offset, int count, char *data)
1264 {
1265         struct smb_sb_info *server = server_from_inode(inode);
1266         __u16 returned_count, data_len;
1267         unsigned char *buf;
1268         int result;
1269
1270         smb_lock_server(server);
1271         smb_setup_header(server, SMBread, 5, 0);
1272         buf = server->packet;
1273         WSET(buf, smb_vwv0, SMB_I(inode)->fileid);
1274         WSET(buf, smb_vwv1, count);
1275         DSET(buf, smb_vwv2, offset);
1276         WSET(buf, smb_vwv4, 0);
1277
1278         result = smb_request_ok(server, SMBread, 5, -1);
1279         if (result < 0)
1280                 goto out;
1281         returned_count = WVAL(server->packet, smb_vwv0);
1282
1283         buf = SMB_BUF(server->packet);
1284         data_len = WVAL(buf, 1);
1285
1286         /* we can NOT simply trust the data_len given by the server ... */
1287         if (data_len > server->packet_size - (buf+3 - server->packet)) {
1288                 printk(KERN_ERR "smb_proc_read: invalid data length!! "
1289                        "%d > %d - (%p - %p)\n",
1290                        data_len, server->packet_size, buf+3, server->packet);
1291                 result = -EIO;
1292                 goto out;
1293         }
1294
1295         memcpy(data, buf+3, data_len);
1296
1297         if (returned_count != data_len) {
1298                 printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
1299                 printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
1300                        returned_count, data_len);
1301         }
1302         result = data_len;
1303
1304 out:
1305         VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
1306                 inode->i_ino, SMB_I(inode)->fileid, count, result);
1307         smb_unlock_server(server);
1308         return result;
1309 }
1310
1311 static int
1312 smb_proc_write(struct inode *inode, loff_t offset, int count, const char *data)
1313 {
1314         struct smb_sb_info *server = server_from_inode(inode);
1315         int result;
1316         __u8 *p;
1317         __u16 fileid = SMB_I(inode)->fileid;
1318
1319         VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld, packet_size=%d\n",
1320                 inode->i_ino, SMB_I(inode)->fileid, count, offset,
1321                 server->packet_size);
1322
1323         smb_lock_server(server);
1324         p = smb_setup_header(server, SMBwrite, 5, count + 3);
1325         WSET(server->packet, smb_vwv0, fileid);
1326         WSET(server->packet, smb_vwv1, count);
1327         DSET(server->packet, smb_vwv2, offset);
1328         WSET(server->packet, smb_vwv4, 0);
1329
1330         *p++ = 1;
1331         WSET(p, 0, count);
1332         memcpy(p+2, data, count);
1333
1334         result = smb_request_ok(server, SMBwrite, 1, 0);
1335         if (result >= 0)
1336                 result = WVAL(server->packet, smb_vwv0);
1337
1338         smb_unlock_server(server);
1339         return result;
1340 }
1341
1342 /*
1343  * In smb_proc_readX and smb_proc_writeX we do not retry, because the
1344  * file-id would not be valid after a reconnection.
1345  */
1346 static int
1347 smb_proc_readX(struct inode *inode, loff_t offset, int count, char *data)
1348 {
1349         struct smb_sb_info *server = server_from_inode(inode);
1350         u16 data_len, data_off;
1351         unsigned char *buf;
1352         int result;
1353
1354         smb_lock_server(server);
1355         smb_setup_header(server, SMBreadX, 12, 0);
1356         buf = server->packet;
1357         WSET(buf, smb_vwv0, 0x00ff);
1358         WSET(buf, smb_vwv1, 0);
1359         WSET(buf, smb_vwv2, SMB_I(inode)->fileid);
1360         DSET(buf, smb_vwv3, (u32)offset);               /* low 32 bits */
1361         WSET(buf, smb_vwv5, count);
1362         WSET(buf, smb_vwv6, 0);
1363         DSET(buf, smb_vwv7, 0);
1364         WSET(buf, smb_vwv9, 0);
1365         DSET(buf, smb_vwv10, (u32)(offset >> 32));      /* high 32 bits */
1366         WSET(buf, smb_vwv11, 0);
1367
1368         result = smb_request_ok(server, SMBreadX, 12, -1);
1369         if (result < 0)
1370                 goto out;
1371         data_len = WVAL(server->packet, smb_vwv5);
1372         data_off = WVAL(server->packet, smb_vwv6);
1373         buf = smb_base(server->packet) + data_off;
1374
1375         /* we can NOT simply trust the info given by the server ... */
1376         if (data_len > server->packet_size - (buf - server->packet)) {
1377                 printk(KERN_ERR "smb_proc_read: invalid data length!! "
1378                        "%d > %d - (%p - %p)\n",
1379                        data_len, server->packet_size, buf, server->packet);
1380                 result = -EIO;
1381                 goto out;
1382         }
1383
1384         memcpy(data, buf, data_len);
1385         result = data_len;
1386
1387 out:
1388         smb_unlock_server(server);
1389         VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
1390                 inode->i_ino, SMB_I(inode)->fileid, count, result);
1391         return result;
1392 }
1393
1394 static int
1395 smb_proc_writeX(struct inode *inode, loff_t offset, int count, const char *data)
1396 {
1397         struct smb_sb_info *server = server_from_inode(inode);
1398         int result;
1399         u8 *p;
1400
1401         VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld, packet_size=%d\n",
1402                 inode->i_ino, SMB_I(inode)->fileid, count, offset,
1403                 server->packet_size);
1404
1405         smb_lock_server(server);
1406         p = smb_setup_header(server, SMBwriteX, 14, count + 2);
1407         WSET(server->packet, smb_vwv0, 0x00ff);
1408         WSET(server->packet, smb_vwv1, 0);
1409         WSET(server->packet, smb_vwv2, SMB_I(inode)->fileid);
1410         DSET(server->packet, smb_vwv3, (u32)offset);    /* low 32 bits */
1411         DSET(server->packet, smb_vwv5, 0);
1412         WSET(server->packet, smb_vwv7, 0);              /* write mode */
1413         WSET(server->packet, smb_vwv8, 0);
1414         WSET(server->packet, smb_vwv9, 0);
1415         WSET(server->packet, smb_vwv10, count);         /* data length */
1416         WSET(server->packet, smb_vwv11, p + 2 - smb_base(server->packet));
1417         DSET(server->packet, smb_vwv12, (u32)(offset >> 32));
1418         *p++ = 0;    /* FIXME: pad to short or long ... change +2 above also */
1419         *p++ = 0;
1420         memcpy(p, data, count);
1421
1422         result = smb_request_ok(server, SMBwriteX, 6, 0);
1423         if (result >= 0)
1424                 result = WVAL(server->packet, smb_vwv2);
1425
1426         smb_unlock_server(server);
1427         return result;
1428 }
1429
1430 int
1431 smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
1432 {
1433         struct smb_sb_info *server = server_from_dentry(dentry);
1434         char *p;
1435         int result;
1436
1437         smb_lock_server(server);
1438
1439       retry:
1440         p = smb_setup_header(server, SMBcreate, 3, 0);
1441         WSET(server->packet, smb_vwv0, attr);
1442         DSET(server->packet, smb_vwv1, utc2local(server, ctime));
1443         result = smb_simple_encode_path(server, &p, dentry, NULL);
1444         if (result < 0)
1445                 goto out;
1446         smb_setup_bcc(server, p);
1447
1448         result = smb_request_ok(server, SMBcreate, 1, 0);
1449         if (result < 0) {
1450                 if (smb_retry(server))
1451                         goto retry;
1452                 goto out;
1453         }
1454         *fileid = WVAL(server->packet, smb_vwv0);
1455         result = 0;
1456
1457 out:
1458         smb_unlock_server(server);
1459         return result;
1460 }
1461
1462 int
1463 smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
1464 {
1465         struct smb_sb_info *server = server_from_dentry(old_dentry);
1466         char *p;
1467         int result;
1468
1469         smb_lock_server(server);
1470
1471       retry:
1472         p = smb_setup_header(server, SMBmv, 1, 0);
1473         WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
1474         result = smb_simple_encode_path(server, &p, old_dentry, NULL);
1475         if (result < 0)
1476                 goto out;
1477         result = smb_simple_encode_path(server, &p, new_dentry, NULL);
1478         if (result < 0)
1479                 goto out;
1480         smb_setup_bcc(server, p);
1481
1482         if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
1483                 if (smb_retry(server))
1484                         goto retry;
1485                 goto out;
1486         }
1487         result = 0;
1488 out:
1489         smb_unlock_server(server);
1490         return result;
1491 }
1492
1493 /*
1494  * Code common to mkdir and rmdir.
1495  */
1496 static int
1497 smb_proc_generic_command(struct dentry *dentry, __u8 command)
1498 {
1499         struct smb_sb_info *server = server_from_dentry(dentry);
1500         char *p;
1501         int result;
1502
1503         smb_lock_server(server);
1504
1505       retry:
1506         p = smb_setup_header(server, command, 0, 0);
1507         result = smb_simple_encode_path(server, &p, dentry, NULL);
1508         if (result < 0)
1509                 goto out;
1510         smb_setup_bcc(server, p);
1511
1512         result = smb_request_ok(server, command, 0, 0);
1513         if (result < 0) {
1514                 if (smb_retry(server))
1515                         goto retry;
1516                 goto out;
1517         }
1518         result = 0;
1519 out:
1520         smb_unlock_server(server);
1521         return result;
1522 }
1523
1524 int
1525 smb_proc_mkdir(struct dentry *dentry)
1526 {
1527         return smb_proc_generic_command(dentry, SMBmkdir);
1528 }
1529
1530 int
1531 smb_proc_rmdir(struct dentry *dentry)
1532 {
1533         return smb_proc_generic_command(dentry, SMBrmdir);
1534 }
1535
1536 #if SMBFS_POSIX_UNLINK
1537 /*
1538  * Removes readonly attribute from a file. Used by unlink to give posix
1539  * semantics.
1540  * Note: called with the server locked.
1541  */
1542 static int
1543 smb_set_rw(struct dentry *dentry,struct smb_sb_info *server)
1544 {
1545         int result;
1546         struct smb_fattr fattr;
1547
1548         /* first get current attribute */
1549         smb_init_dirent(server, &fattr);
1550         result = server->ops->getattr(server, dentry, &fattr);
1551         smb_finish_dirent(server, &fattr);
1552         if (result < 0)
1553                 return result;
1554
1555         /* if RONLY attribute is set, remove it */
1556         if (fattr.attr & aRONLY) {  /* read only attribute is set */
1557                 fattr.attr &= ~aRONLY;
1558                 result = smb_proc_setattr_core(server, dentry, fattr.attr);
1559         }
1560         return result;
1561 }
1562 #endif
1563
1564 int
1565 smb_proc_unlink(struct dentry *dentry)
1566 {
1567         struct smb_sb_info *server = server_from_dentry(dentry);
1568         int flag = 0;
1569         char *p;
1570         int result;
1571
1572         smb_lock_server(server);
1573
1574       retry:
1575         p = smb_setup_header(server, SMBunlink, 1, 0);
1576         WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
1577         result = smb_simple_encode_path(server, &p, dentry, NULL);
1578         if (result < 0)
1579                 goto out;
1580         smb_setup_bcc(server, p);
1581
1582         if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
1583 #if SMBFS_POSIX_UNLINK
1584                 if (result == -EACCES && !flag) {
1585                         /* Posix semantics is for the read-only state
1586                            of a file to be ignored in unlink(). In the
1587                            SMB world a unlink() is refused on a
1588                            read-only file. To make things easier for
1589                            unix users we try to override the files
1590                            permission if the unlink fails with the
1591                            right error.
1592                            This introduces a race condition that could
1593                            lead to a file being written by someone who
1594                            shouldn't have access, but as far as I can
1595                            tell that is unavoidable */
1596
1597                         /* remove RONLY attribute and try again */
1598                         result = smb_set_rw(dentry,server);
1599                         if (result == 0) {
1600                                 flag = 1;
1601                                 goto retry;
1602                         }
1603                 }
1604 #endif
1605                 if (smb_retry(server))
1606                         goto retry;
1607                 goto out;
1608         }
1609         result = 0;
1610 out:
1611         smb_unlock_server(server);
1612         return result;
1613 }
1614
1615 /*
1616  * Called with the server locked
1617  */
1618 int
1619 smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
1620 {
1621         smb_setup_header(server, SMBflush, 1, 0);
1622         WSET(server->packet, smb_vwv0, fileid);
1623         return smb_request_ok(server, SMBflush, 0, 0);
1624 }
1625
1626 static int
1627 smb_proc_trunc32(struct inode *inode, loff_t length)
1628 {
1629         /*
1630          * Writing 0bytes is old-SMB magic for truncating files.
1631          * MAX_NON_LFS should prevent this from being called with a too
1632          * large offset.
1633          */
1634         return smb_proc_write(inode, length, 0, NULL);
1635 }
1636
1637 static int
1638 smb_proc_trunc64(struct inode *inode, loff_t length)
1639 {
1640         struct smb_sb_info *server = server_from_inode(inode);
1641         int command;
1642         int result;
1643         char *param = server->temp_buf;
1644         char data[8];
1645         unsigned char *resp_data = NULL;
1646         unsigned char *resp_param = NULL;
1647         int resp_data_len = 0;
1648         int resp_param_len = 0;
1649
1650         smb_lock_server(server);
1651         command = TRANSACT2_SETFILEINFO;
1652  
1653         /* FIXME: must we also set allocation size? winNT seems to do that */
1654 retry:
1655         WSET(param, 0, SMB_I(inode)->fileid);
1656         WSET(param, 2, SMB_SET_FILE_END_OF_FILE_INFO);
1657         WSET(param, 4, 0);
1658         LSET(data, 0, length);
1659         result = smb_trans2_request(server, command,
1660                                     8, data, 6, param,
1661                                     &resp_data_len, &resp_data,
1662                                     &resp_param_len, &resp_param);
1663         if (result < 0) {
1664                 if (smb_retry(server))
1665                         goto retry;
1666                 goto out;
1667         }
1668         result = 0;
1669         if (server->rcls != 0)
1670                 result = smb_errno(server);
1671
1672 out:
1673         smb_unlock_server(server);
1674         return result;
1675 }
1676
1677 static int
1678 smb_proc_trunc95(struct inode *inode, loff_t length)
1679 {
1680         struct smb_sb_info *server = server_from_inode(inode);
1681         int result = smb_proc_trunc32(inode, length);
1682  
1683         /*
1684          * win9x doesn't appear to update the size immediately.
1685          * It will return the old file size after the truncate,
1686          * confusing smbfs. So we force an update.
1687          *
1688          * FIXME: is this still necessary?
1689          */
1690         smb_lock_server(server);
1691         smb_proc_flush(server, SMB_I(inode)->fileid);
1692         smb_unlock_server(server);
1693         return result;
1694 }
1695
1696 static void
1697 smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
1698 {
1699         memset(fattr, 0, sizeof(*fattr));
1700
1701         fattr->f_nlink = 1;
1702         fattr->f_uid = server->mnt->uid;
1703         fattr->f_gid = server->mnt->gid;
1704         fattr->f_blksize = SMB_ST_BLKSIZE;
1705 }
1706
1707 static void
1708 smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
1709 {
1710         fattr->f_mode = server->mnt->file_mode;
1711         if (fattr->attr & aDIR)
1712         {
1713                 fattr->f_mode = server->mnt->dir_mode;
1714                 fattr->f_size = SMB_ST_BLKSIZE;
1715         }
1716         /* Check the read-only flag */
1717         if (fattr->attr & aRONLY)
1718                 fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
1719
1720         /* How many 512 byte blocks do we need for this file? */
1721         fattr->f_blocks = 0;
1722         if (fattr->f_size != 0)
1723                 fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);
1724         return;
1725 }
1726
1727 void
1728 smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
1729 {
1730         smb_init_dirent(server, fattr);
1731         fattr->attr = aDIR;
1732         fattr->f_ino = 2; /* traditional root inode number */
1733         fattr->f_mtime = CURRENT_TIME;
1734         smb_finish_dirent(server, fattr);
1735 }
1736
1737 /*
1738  * Decode a dirent for old protocols
1739  *
1740  * qname is filled with the decoded, and possibly translated, name.
1741  * fattr receives decoded attributes
1742  *
1743  * Bugs Noted:
1744  * (1) Pathworks servers may pad the name with extra spaces.
1745  */
1746 static char *
1747 smb_decode_short_dirent(struct smb_sb_info *server, char *p,
1748                         struct qstr *qname, struct smb_fattr *fattr)
1749 {
1750         int len;
1751
1752         /*
1753          * SMB doesn't have a concept of inode numbers ...
1754          */
1755         smb_init_dirent(server, fattr);
1756         fattr->f_ino = 0;       /* FIXME: do we need this? */
1757
1758         p += SMB_STATUS_SIZE;   /* reserved (search_status) */
1759         fattr->attr = *p;
1760         fattr->f_mtime = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
1761         fattr->f_size = DVAL(p, 5);
1762         fattr->f_ctime = fattr->f_mtime;
1763         fattr->f_atime = fattr->f_mtime;
1764         qname->name = p + 9;
1765         len = strnlen(qname->name, 12);
1766
1767         /*
1768          * Trim trailing blanks for Pathworks servers
1769          */
1770         while (len > 2 && qname->name[len-1] == ' ')
1771                 len--;
1772
1773         smb_finish_dirent(server, fattr);
1774
1775 #if 0
1776         /* FIXME: These only work for ascii chars, and recent smbmount doesn't
1777            allow the flag to be set anyway. It kills const. Remove? */
1778         switch (server->opt.case_handling) {
1779         case SMB_CASE_UPPER:
1780                 str_upper(entry->name, len);
1781                 break;
1782         case SMB_CASE_LOWER:
1783                 str_lower(entry->name, len);
1784                 break;
1785         default:
1786                 break;
1787         }
1788 #endif
1789
1790         qname->len = 0;
1791         len = server->ops->convert(server->name_buf, SMB_MAXNAMELEN,
1792                                    qname->name, len,
1793                                    server->remote_nls, server->local_nls);
1794         if (len > 0) {
1795                 qname->len = len;
1796                 qname->name = server->name_buf;
1797                 DEBUG1("len=%d, name=%.*s\n",qname->len,qname->len,qname->name);
1798         }
1799
1800         return p + 22;
1801 }
1802
1803 /*
1804  * This routine is used to read in directory entries from the network.
1805  * Note that it is for short directory name seeks, i.e.: protocol <
1806  * SMB_PROTOCOL_LANMAN2
1807  */
1808 static int
1809 smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
1810                        struct smb_cache_control *ctl)
1811 {
1812         struct dentry *dir = filp->f_dentry;
1813         struct smb_sb_info *server = server_from_dentry(dir);
1814         struct qstr qname;
1815         struct smb_fattr fattr;
1816         char *p;
1817         int result;
1818         int i, first, entries_seen, entries;
1819         int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE;
1820         __u16 bcc;
1821         __u16 count;
1822         char status[SMB_STATUS_SIZE];
1823         static struct qstr mask = { "*.*", 3, 0 };
1824         unsigned char *last_status;
1825
1826         VERBOSE("%s/%s\n", DENTRY_PATH(dir));
1827
1828         smb_lock_server(server);
1829
1830         first = 1;
1831         entries = 0;
1832         entries_seen = 2; /* implicit . and .. */
1833
1834         while (1) {
1835                 p = smb_setup_header(server, SMBsearch, 2, 0);
1836                 WSET(server->packet, smb_vwv0, entries_asked);
1837                 WSET(server->packet, smb_vwv1, aDIR);
1838                 if (first == 1) {
1839                         result = smb_simple_encode_path(server, &p, dir, &mask);
1840                         if (result < 0)
1841                                 goto unlock_return;
1842                         if (p + 3 > (char*)server->packet+server->packet_size) {
1843                                 result = -ENAMETOOLONG;
1844                                 goto unlock_return;
1845                         }
1846                         *p++ = 5;
1847                         WSET(p, 0, 0);
1848                         p += 2;
1849                         first = 0;
1850                 } else {
1851                         if (p + 5 + SMB_STATUS_SIZE >
1852                             (char*)server->packet + server->packet_size) {
1853                                 result = -ENAMETOOLONG;
1854                                 goto unlock_return;
1855                         }
1856                                 
1857                         *p++ = 4;
1858                         *p++ = 0;
1859                         *p++ = 5;
1860                         WSET(p, 0, SMB_STATUS_SIZE);
1861                         p += 2;
1862                         memcpy(p, status, SMB_STATUS_SIZE);
1863                         p += SMB_STATUS_SIZE;
1864                 }
1865
1866                 smb_setup_bcc(server, p);
1867
1868                 result = smb_request_ok(server, SMBsearch, 1, -1);
1869                 if (result < 0) {
1870                         if ((server->rcls == ERRDOS) && 
1871                             (server->err  == ERRnofiles))
1872                                 break;
1873                         if (smb_retry(server)) {
1874                                 ctl->idx = -1;  /* retry */
1875                                 result = 0;
1876                         }
1877                         goto unlock_return;
1878                 }
1879                 p = SMB_VWV(server->packet);
1880                 count = WVAL(p, 0);
1881                 if (count <= 0)
1882                         break;
1883
1884                 result = -EIO;
1885                 bcc = WVAL(p, 2);
1886                 if (bcc != count * SMB_DIRINFO_SIZE + 3)
1887                         goto unlock_return;
1888                 p += 7;
1889
1890
1891                 /* Make sure the response fits in the buffer. Fixed sized 
1892                    entries means we don't have to check in the decode loop. */
1893
1894                 last_status = SMB_BUF(server->packet) + 3 + (count - 1) *
1895                         SMB_DIRINFO_SIZE;
1896
1897                 if (last_status + SMB_DIRINFO_SIZE >=
1898                     server->packet + server->packet_size) {
1899                         printk(KERN_ERR "smb_proc_readdir_short: "
1900                                "last dir entry outside buffer! "
1901                                "%d@%p  %d@%p\n", SMB_DIRINFO_SIZE, last_status,
1902                                server->packet_size, server->packet);
1903                         goto unlock_return;
1904                 }
1905
1906                 /* Read the last entry into the status field. */
1907                 memcpy(status, last_status, SMB_STATUS_SIZE);
1908
1909
1910                 /* Now we are ready to parse smb directory entries. */
1911
1912                 for (i = 0; i < count; i++) {
1913                         p = smb_decode_short_dirent(server, p, 
1914                                                     &qname, &fattr);
1915                         if (qname.len == 0)
1916                                 continue;
1917
1918                         if (entries_seen == 2 && qname.name[0] == '.') {
1919                                 if (qname.len == 1)
1920                                         continue;
1921                                 if (qname.name[1] == '.' && qname.len == 2)
1922                                         continue;
1923                         }
1924                         if (!smb_fill_cache(filp, dirent, filldir, ctl, 
1925                                             &qname, &fattr))
1926                                 ;       /* stop reading? */
1927                         entries_seen++;
1928                 }
1929         }
1930         result = entries;
1931
1932 unlock_return:
1933         smb_unlock_server(server);
1934         return result;
1935 }
1936
1937 /*
1938  * Interpret a long filename structure using the specified info level:
1939  *   level 1 for anything below NT1 protocol
1940  *   level 260 for NT1 protocol
1941  *
1942  * qname is filled with the decoded, and possibly translated, name
1943  * fattr receives decoded attributes.
1944  *
1945  * Bugs Noted:
1946  * (1) Win NT 4.0 appends a null byte to names and counts it in the length!
1947  */
1948 static char *
1949 smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
1950                        struct qstr *qname, struct smb_fattr *fattr)
1951 {
1952         char *result;
1953         unsigned int len = 0;
1954         int n;
1955         __u16 date, time;
1956
1957         /*
1958          * SMB doesn't have a concept of inode numbers ...
1959          */
1960         smb_init_dirent(server, fattr);
1961         fattr->f_ino = 0;       /* FIXME: do we need this? */
1962
1963         switch (level) {
1964         case 1:
1965                 len = *((unsigned char *) p + 22);
1966                 qname->name = p + 23;
1967                 result = p + 24 + len;
1968
1969                 date = WVAL(p, 0);
1970                 time = WVAL(p, 2);
1971                 fattr->f_ctime = date_dos2unix(server, date, time);
1972
1973                 date = WVAL(p, 4);
1974                 time = WVAL(p, 6);
1975                 fattr->f_atime = date_dos2unix(server, date, time);
1976
1977                 date = WVAL(p, 8);
1978                 time = WVAL(p, 10);
1979                 fattr->f_mtime = date_dos2unix(server, date, time);
1980                 fattr->f_size = DVAL(p, 12);
1981                 /* ULONG allocation size */
1982                 fattr->attr = WVAL(p, 20);
1983
1984                 VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
1985                         p, len, len, qname->name);
1986                 break;
1987         case 260:
1988                 result = p + WVAL(p, 0);
1989                 len = DVAL(p, 60);
1990                 if (len > 255) len = 255;
1991                 /* NT4 null terminates */
1992                 qname->name = p + 94;
1993                 if (len && qname->name[len-1] == '\0')
1994                         len--;
1995
1996                 fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 8));
1997                 fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 16));
1998                 fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 24));
1999                 /* change time (32) */
2000                 fattr->f_size = LVAL(p, 40);
2001                 /* alloc size (48) */
2002                 fattr->attr = DVAL(p, 56);
2003
2004                 VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
2005                         p, len, len, qname->name);
2006                 break;
2007         default:
2008                 PARANOIA("Unknown info level %d\n", level);
2009                 result = p + WVAL(p, 0);
2010                 goto out;
2011         }
2012
2013         smb_finish_dirent(server, fattr);
2014
2015 #if 0
2016         /* FIXME: These only work for ascii chars, and recent smbmount doesn't
2017            allow the flag to be set anyway. Remove? */
2018         switch (server->opt.case_handling) {
2019         case SMB_CASE_UPPER:
2020                 str_upper(qname->name, len);
2021                 break;
2022         case SMB_CASE_LOWER:
2023                 str_lower(qname->name, len);
2024                 break;
2025         default:
2026                 break;
2027         }
2028 #endif
2029
2030         qname->len = 0;
2031         n = server->ops->convert(server->name_buf, SMB_MAXNAMELEN,
2032                                  qname->name, len,
2033                                  server->remote_nls, server->local_nls);
2034         if (n > 0) {
2035                 qname->len = n;
2036                 qname->name = server->name_buf;
2037         }
2038
2039 out:
2040         return result;
2041 }
2042
2043 /* findfirst/findnext flags */
2044 #define SMB_CLOSE_AFTER_FIRST (1<<0)
2045 #define SMB_CLOSE_IF_END (1<<1)
2046 #define SMB_REQUIRE_RESUME_KEY (1<<2)
2047 #define SMB_CONTINUE_BIT (1<<3)
2048
2049 /*
2050  * Note: samba-2.0.7 (at least) has a very similar routine, cli_list, in
2051  * source/libsmb/clilist.c. When looking for smb bugs in the readdir code,
2052  * go there for advise.
2053  *
2054  * Bugs Noted:
2055  * (1) When using Info Level 1 Win NT 4.0 truncates directory listings 
2056  * for certain patterns of names and/or lengths. The breakage pattern
2057  * is completely reproducible and can be toggled by the creation of a
2058  * single file. (E.g. echo hi >foo breaks, rm -f foo works.)
2059  */
2060 static int
2061 smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
2062                       struct smb_cache_control *ctl)
2063 {
2064         struct dentry *dir = filp->f_dentry;
2065         struct smb_sb_info *server = server_from_dentry(dir);
2066         struct qstr qname;
2067         struct smb_fattr fattr;
2068
2069         unsigned char *p, *lastname;
2070         char *mask, *param = server->temp_buf;
2071         __u16 command;
2072         int first, entries_seen;
2073
2074         /* Both NT and OS/2 accept info level 1 (but see note below). */
2075         int info_level = 260;
2076         const int max_matches = 512;
2077
2078         unsigned char *resp_data = NULL;
2079         unsigned char *resp_param = NULL;
2080         int resp_data_len = 0;
2081         int resp_param_len = 0;
2082         int ff_searchcount = 0;
2083         int ff_eos = 0;
2084         int ff_lastname = 0;
2085         int ff_dir_handle = 0;
2086         int loop_count = 0;
2087         int mask_len, i, result;
2088         static struct qstr star = { "*", 1, 0 };
2089
2090         /*
2091          * use info level 1 for older servers that don't do 260
2092          */
2093         if (server->opt.protocol < SMB_PROTOCOL_NT1)
2094                 info_level = 1;
2095
2096         smb_lock_server(server);
2097
2098         /*
2099          * Encode the initial path
2100          */
2101         mask = param + 12;
2102
2103         mask_len = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dir, &star);
2104         if (mask_len < 0) {
2105                 result = mask_len;
2106                 goto unlock_return;
2107         }
2108         mask_len--;     /* mask_len is strlen, not #bytes */
2109         first = 1;
2110         VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask);
2111
2112         result = 0;
2113         entries_seen = 2;
2114         ff_eos = 0;
2115
2116         while (ff_eos == 0) {
2117                 loop_count += 1;
2118                 if (loop_count > 10) {
2119                         printk(KERN_WARNING "smb_proc_readdir_long: "
2120                                "Looping in FIND_NEXT??\n");
2121                         result = -EIO;
2122                         break;
2123                 }
2124
2125                 if (first != 0) {
2126                         command = TRANSACT2_FINDFIRST;
2127                         WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
2128                         WSET(param, 2, max_matches);    /* max count */
2129                         WSET(param, 4, SMB_CLOSE_IF_END);
2130                         WSET(param, 6, info_level);
2131                         DSET(param, 8, 0);
2132                 } else {
2133                         command = TRANSACT2_FINDNEXT;
2134
2135                         VERBOSE("handle=0x%X, lastname=%d, mask=%s\n",
2136                                 ff_dir_handle, ff_lastname, mask);
2137
2138                         WSET(param, 0, ff_dir_handle);  /* search handle */
2139                         WSET(param, 2, max_matches);    /* max count */
2140                         WSET(param, 4, info_level);
2141                         DSET(param, 6, 0);
2142                         WSET(param, 10, SMB_CONTINUE_BIT|SMB_CLOSE_IF_END);
2143                 }
2144
2145                 result = smb_trans2_request(server, command,
2146                                             0, NULL, 12 + mask_len + 1, param,
2147                                             &resp_data_len, &resp_data,
2148                                             &resp_param_len, &resp_param);
2149
2150                 if (result < 0) {
2151                         if (smb_retry(server)) {
2152                                 PARANOIA("error=%d, retrying\n", result);
2153                                 ctl->idx = -1;  /* retry */
2154                                 result = 0;
2155                                 goto unlock_return;
2156                         }
2157                         PARANOIA("error=%d, breaking\n", result);
2158                         break;
2159                 }
2160
2161                 if (server->rcls == ERRSRV && server->err == ERRerror) {
2162                         /* a damn Win95 bug - sometimes it clags if you 
2163                            ask it too fast */
2164                         current->state = TASK_INTERRUPTIBLE;
2165                         schedule_timeout(HZ/5);
2166                         continue;
2167                 }
2168
2169                 if (server->rcls != 0) {
2170                         result = smb_errno(server);
2171                         PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
2172                                  mask, result, server->rcls, server->err);
2173                         break;
2174                 }
2175
2176                 /* parse out some important return info */
2177                 if (first != 0) {
2178                         ff_dir_handle = WVAL(resp_param, 0);
2179                         ff_searchcount = WVAL(resp_param, 2);
2180                         ff_eos = WVAL(resp_param, 4);
2181                         ff_lastname = WVAL(resp_param, 8);
2182                 } else {
2183                         ff_searchcount = WVAL(resp_param, 0);
2184                         ff_eos = WVAL(resp_param, 2);
2185                         ff_lastname = WVAL(resp_param, 6);
2186                 }
2187
2188                 if (ff_searchcount == 0)
2189                         break;
2190
2191                 /*
2192                  * We might need the lastname for continuations.
2193                  *
2194                  * Note that some servers (win95?) point to the filename and
2195                  * others (NT4, Samba using NT1) to the dir entry. We assume
2196                  * here that those who do not point to a filename do not need
2197                  * this info to continue the listing.
2198                  *
2199                  * OS/2 needs this and talks infolevel 1
2200                  * NetApps want lastname with infolevel 260
2201                  *
2202                  * Both are happy if we return the data they point to. So we do.
2203                  */
2204                 mask_len = 0;
2205                 if (ff_lastname > 0 && ff_lastname < resp_data_len) {
2206                         lastname = resp_data + ff_lastname;
2207
2208                         switch (info_level) {
2209                         case 260:
2210                                 mask_len = resp_data_len - ff_lastname;
2211                                 break;
2212                         case 1:
2213                                 /* lastname points to a length byte */
2214                                 mask_len = *lastname++;
2215                                 if (ff_lastname + 1 + mask_len > resp_data_len)
2216                                         mask_len = resp_data_len - ff_lastname - 1;
2217                                 break;
2218                         }
2219
2220                         /*
2221                          * Update the mask string for the next message.
2222                          */
2223                         if (mask_len < 0)
2224                                 mask_len = 0;
2225                         if (mask_len > 255)
2226                                 mask_len = 255;
2227                         if (mask_len)
2228                                 strncpy(mask, lastname, mask_len);
2229                 }
2230                 mask_len = strnlen(mask, mask_len);
2231                 VERBOSE("new mask, len=%d@%d of %d, mask=%.*s\n",
2232                         mask_len, ff_lastname, resp_data_len, mask_len, mask);
2233
2234                 /* Now we are ready to parse smb directory entries. */
2235
2236                 /* point to the data bytes */
2237                 p = resp_data;
2238                 for (i = 0; i < ff_searchcount; i++) {
2239                         /* make sure we stay within the buffer */
2240                         if (p >= resp_data + resp_data_len) {
2241                                 printk(KERN_ERR "smb_proc_readdir_long: "
2242                                        "dirent pointer outside buffer! "
2243                                        "%p  %d@%p  %d@%p\n",
2244                                        p, resp_data_len, resp_data,
2245                                        server->packet_size, server->packet);
2246                                 result = -EIO; /* always a comm. error? */
2247                                 goto unlock_return;
2248                         }
2249
2250                         p = smb_decode_long_dirent(server, p, info_level,
2251                                                    &qname, &fattr);
2252
2253                         /* ignore . and .. from the server */
2254                         if (entries_seen == 2 && qname.name[0] == '.') {
2255                                 if (qname.len == 1)
2256                                         continue;
2257                                 if (qname.name[1] == '.' && qname.len == 2)
2258                                         continue;
2259                         }
2260
2261                         if (!smb_fill_cache(filp, dirent, filldir, ctl, 
2262                                             &qname, &fattr))
2263                                 ;       /* stop reading? */
2264                         entries_seen++;
2265                 }
2266
2267                 VERBOSE("received %d entries, eos=%d\n", ff_searchcount,ff_eos);
2268
2269                 first = 0;
2270                 loop_count = 0;
2271         }
2272
2273 unlock_return:
2274         smb_unlock_server(server);
2275         return result;
2276 }
2277
2278 /*
2279  * This version uses the trans2 TRANSACT2_FINDFIRST message 
2280  * to get the attribute data.
2281  * Note: called with the server locked.
2282  *
2283  * Bugs Noted:
2284  */
2285 static int
2286 smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
2287                         struct smb_fattr *fattr)
2288 {
2289         char *param = server->temp_buf, *mask = param + 12;
2290         __u16 date, time;
2291         unsigned char *resp_data = NULL;
2292         unsigned char *resp_param = NULL;
2293         int resp_data_len = 0;
2294         int resp_param_len = 0;
2295         int mask_len, result;
2296
2297 retry:
2298         mask_len = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dentry,NULL);
2299         if (mask_len < 0) {
2300                 result = mask_len;
2301                 goto out;
2302         }
2303         VERBOSE("name=%s, len=%d\n", mask, mask_len);
2304         WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
2305         WSET(param, 2, 1);      /* max count */
2306         WSET(param, 4, 1);      /* close after this call */
2307         WSET(param, 6, 1);      /* info_level */
2308         DSET(param, 8, 0);
2309
2310         result = smb_trans2_request(server, TRANSACT2_FINDFIRST,
2311                                     0, NULL, 12 + mask_len, param,
2312                                     &resp_data_len, &resp_data,
2313                                     &resp_param_len, &resp_param);
2314         if (result < 0)
2315         {
2316                 if (smb_retry(server))
2317                         goto retry;
2318                 goto out;
2319         }
2320         if (server->rcls != 0)
2321         { 
2322                 result = smb_errno(server);
2323 #ifdef SMBFS_PARANOIA
2324                 if (result != -ENOENT)
2325                         PARANOIA("error for %s, rcls=%d, err=%d\n",
2326                                  mask, server->rcls, server->err);
2327 #endif
2328                 goto out;
2329         }
2330         /* Make sure we got enough data ... */
2331         result = -EINVAL;
2332         if (resp_data_len < 22 || WVAL(resp_param, 2) != 1)
2333         {
2334                 PARANOIA("bad result for %s, len=%d, count=%d\n",
2335                          mask, resp_data_len, WVAL(resp_param, 2));
2336                 goto out;
2337         }
2338
2339         /*
2340          * Decode the response into the fattr ...
2341          */
2342         date = WVAL(resp_data, 0);
2343         time = WVAL(resp_data, 2);
2344         fattr->f_ctime = date_dos2unix(server, date, time);
2345
2346         date = WVAL(resp_data, 4);
2347         time = WVAL(resp_data, 6);
2348         fattr->f_atime = date_dos2unix(server, date, time);
2349
2350         date = WVAL(resp_data, 8);
2351         time = WVAL(resp_data, 10);
2352         fattr->f_mtime = date_dos2unix(server, date, time);
2353         VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
2354                 mask, date, time, fattr->f_mtime);
2355         fattr->f_size = DVAL(resp_data, 12);
2356         /* ULONG allocation size */
2357         fattr->attr = WVAL(resp_data, 20);
2358         result = 0;
2359
2360 out:
2361         return result;
2362 }
2363
2364 /*
2365  * Note: called with the server locked.
2366  */
2367 static int
2368 smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
2369                       struct smb_fattr *fattr)
2370 {
2371         int result;
2372         char *p;
2373
2374       retry:
2375         p = smb_setup_header(server, SMBgetatr, 0, 0);
2376         result = smb_simple_encode_path(server, &p, dir, NULL);
2377         if (result < 0)
2378                 goto out;
2379         smb_setup_bcc(server, p);
2380
2381         if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
2382         {
2383                 if (smb_retry(server))
2384                         goto retry;
2385                 goto out;
2386         }
2387         fattr->attr    = WVAL(server->packet, smb_vwv0);
2388         fattr->f_mtime = local2utc(server, DVAL(server->packet, smb_vwv1));
2389         fattr->f_size  = DVAL(server->packet, smb_vwv3);
2390         fattr->f_ctime = fattr->f_mtime; 
2391         fattr->f_atime = fattr->f_mtime; 
2392 #ifdef SMBFS_DEBUG_TIMESTAMP
2393         printk("getattr_core: %s/%s, mtime=%ld\n",
2394                DENTRY_PATH(dir), fattr->f_mtime);
2395 #endif
2396         result = 0;
2397
2398 out:
2399         return result;
2400 }
2401
2402 /*
2403  * Note: called with the server locked.
2404  *
2405  * Bugs Noted:
2406  * (1) Win 95 swaps the date and time fields in the standard info level.
2407  */
2408 static int
2409 smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
2410                         int *lrdata, unsigned char **rdata,
2411                         int *lrparam, unsigned char **rparam,
2412                         int infolevel)
2413 {
2414         char *p, *param = server->temp_buf;
2415         int result;
2416
2417 retry:
2418         WSET(param, 0, infolevel);
2419         DSET(param, 2, 0);
2420         result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
2421         if (result < 0)
2422                 goto out;
2423         p = param + 6 + result;
2424
2425         result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
2426                                     0, NULL, p - param, param,
2427                                     lrdata, rdata,
2428                                     lrparam, rparam);
2429         if (result < 0)
2430         {
2431                 if (smb_retry(server))
2432                         goto retry;
2433                 goto out;
2434         }
2435         if (server->rcls != 0)
2436         {
2437                 VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
2438                         &param[6], result, server->rcls, server->err);
2439                 result = smb_errno(server);
2440                 goto out;
2441         }
2442         result = -ENOENT;
2443         if (*lrdata < 22)
2444         {
2445                 PARANOIA("not enough data for %s, len=%d\n",
2446                          &param[6], *lrdata);
2447                 goto out;
2448         }
2449
2450         result = 0;
2451 out:
2452         return result;
2453 }
2454
2455 static int
2456 smb_proc_getattr_trans2_std(struct smb_sb_info *server, struct dentry *dir,
2457                             struct smb_fattr *attr)
2458 {
2459         u16 date, time;
2460         int off_date = 0, off_time = 2;
2461         unsigned char *resp_data = NULL;
2462         unsigned char *resp_param = NULL;
2463         int resp_data_len = 0;
2464         int resp_param_len = 0;
2465
2466         int result = smb_proc_getattr_trans2(server, dir,
2467                                              &resp_data_len, &resp_data,
2468                                              &resp_param_len, &resp_param,
2469                                              SMB_INFO_STANDARD);
2470         if (result < 0)
2471                 goto out;
2472
2473         /*
2474          * Kludge alert: Win 95 swaps the date and time field,
2475          * contrary to the CIFS docs and Win NT practice.
2476          */
2477         if (server->mnt->flags & SMB_MOUNT_WIN95) {
2478                 off_date = 2;
2479                 off_time = 0;
2480         }
2481         date = WVAL(resp_data, off_date);
2482         time = WVAL(resp_data, off_time);
2483         attr->f_ctime = date_dos2unix(server, date, time);
2484
2485         date = WVAL(resp_data, 4 + off_date);
2486         time = WVAL(resp_data, 4 + off_time);
2487         attr->f_atime = date_dos2unix(server, date, time);
2488
2489         date = WVAL(resp_data, 8 + off_date);
2490         time = WVAL(resp_data, 8 + off_time);
2491         attr->f_mtime = date_dos2unix(server, date, time);
2492 #ifdef SMBFS_DEBUG_TIMESTAMP
2493         printk(KERN_DEBUG "getattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n",
2494                DENTRY_PATH(dir), date, time, attr->f_mtime);
2495 #endif
2496         attr->f_size = DVAL(resp_data, 12);
2497         attr->attr = WVAL(resp_data, 20);
2498
2499 out:
2500         return result;
2501 }
2502
2503 static int
2504 smb_proc_getattr_trans2_all(struct smb_sb_info *server, struct dentry *dir,
2505                             struct smb_fattr *attr)
2506 {
2507         unsigned char *resp_data = NULL;
2508         unsigned char *resp_param = NULL;
2509         int resp_data_len = 0;
2510         int resp_param_len = 0;
2511  
2512         int result = smb_proc_getattr_trans2(server, dir,
2513                                              &resp_data_len, &resp_data,
2514                                              &resp_param_len, &resp_param,
2515                                              SMB_QUERY_FILE_ALL_INFO);
2516         if (result < 0)
2517                 goto out;
2518  
2519         attr->f_ctime = smb_ntutc2unixutc(LVAL(resp_data, 0));
2520         attr->f_atime = smb_ntutc2unixutc(LVAL(resp_data, 8));
2521         attr->f_mtime = smb_ntutc2unixutc(LVAL(resp_data, 16));
2522         /* change (24) */
2523         attr->attr = WVAL(resp_data, 32);
2524         /* pad? (34) */
2525         /* allocated size (40) */
2526         attr->f_size = LVAL(resp_data, 48);
2527
2528 out:
2529         return result;
2530 }
2531
2532 static int
2533 smb_proc_getattr_95(struct smb_sb_info *server, struct dentry *dir,
2534                     struct smb_fattr *attr)
2535 {
2536         struct inode *inode = dir->d_inode;
2537         int result;
2538
2539         /* FIXME: why not use the "all" version? */
2540         result = smb_proc_getattr_trans2_std(server, dir, attr);
2541         if (result < 0)
2542                 goto out;
2543
2544         /*
2545          * None of the getattr versions here can make win9x return the right
2546          * filesize if there are changes made to an open file.
2547          * A seek-to-end does return the right size, but we only need to do
2548          * that on files we have written.
2549          */
2550         if (inode && SMB_I(inode)->flags & SMB_F_LOCALWRITE &&
2551             smb_is_open(inode))
2552         {
2553                 __u16 fileid = SMB_I(inode)->fileid;
2554                 attr->f_size = smb_proc_seek(server, fileid, 2, 0);
2555         }
2556
2557 out:
2558         return result;
2559 }
2560
2561 int
2562 smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
2563 {
2564         struct smb_sb_info *server = server_from_dentry(dir);
2565         int result;
2566
2567         smb_lock_server(server);
2568
2569         smb_init_dirent(server, fattr);
2570         result = server->ops->getattr(server, dir, fattr);
2571         smb_finish_dirent(server, fattr);
2572
2573         smb_unlock_server(server);
2574         return result;
2575 }
2576
2577
2578 /*
2579  * Called with the server locked. Because of bugs in the
2580  * core protocol, we use this only to set attributes. See
2581  * smb_proc_settime() below for timestamp handling.
2582  *
2583  * Bugs Noted:
2584  * (1) If mtime is non-zero, both Win 3.1 and Win 95 fail
2585  * with an undocumented error (ERRDOS code 50). Setting
2586  * mtime to 0 allows the attributes to be set.
2587  * (2) The extra parameters following the name string aren't
2588  * in the CIFS docs, but seem to be necessary for operation.
2589  */
2590 static int
2591 smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
2592                       __u16 attr)
2593 {
2594         char *p;
2595         int result;
2596
2597       retry:
2598         p = smb_setup_header(server, SMBsetatr, 8, 0);
2599         WSET(server->packet, smb_vwv0, attr);
2600         DSET(server->packet, smb_vwv1, 0); /* mtime */
2601         WSET(server->packet, smb_vwv3, 0); /* reserved values */
2602         WSET(server->packet, smb_vwv4, 0);
2603         WSET(server->packet, smb_vwv5, 0);
2604         WSET(server->packet, smb_vwv6, 0);
2605         WSET(server->packet, smb_vwv7, 0);
2606         result = smb_simple_encode_path(server, &p, dentry, NULL);
2607         if (result < 0)
2608                 goto out;
2609         if (p + 2 > (char *)server->packet + server->packet_size) {
2610                 result = -ENAMETOOLONG;
2611                 goto out;
2612         }
2613         *p++ = 4;
2614         *p++ = 0;
2615         smb_setup_bcc(server, p);
2616
2617         result = smb_request_ok(server, SMBsetatr, 0, 0);
2618         if (result < 0) {
2619                 if (smb_retry(server))
2620                         goto retry;
2621                 goto out;
2622         }
2623         result = 0;
2624 out:
2625         return result;
2626 }
2627
2628 /*
2629  * Because of bugs in the trans2 setattr messages, we must set
2630  * attributes and timestamps separately. The core SMBsetatr
2631  * message seems to be the only reliable way to set attributes.
2632  */
2633 int
2634 smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr)
2635 {
2636         struct smb_sb_info *server = server_from_dentry(dir);
2637         int result;
2638
2639         VERBOSE("setting %s/%s, open=%d\n", 
2640                 DENTRY_PATH(dir), smb_is_open(dir->d_inode));
2641         smb_lock_server(server);
2642         result = smb_proc_setattr_core(server, dir, fattr->attr);
2643         smb_unlock_server(server);
2644         return result;
2645 }
2646
2647 /*
2648  * Called with the server locked. Sets the timestamps for an
2649  * file open with write permissions.
2650  */
2651 static int
2652 smb_proc_setattr_ext(struct smb_sb_info *server,
2653                       struct inode *inode, struct smb_fattr *fattr)
2654 {
2655         __u16 date, time;
2656         int result;
2657
2658       retry:
2659         smb_setup_header(server, SMBsetattrE, 7, 0);
2660         WSET(server->packet, smb_vwv0, SMB_I(inode)->fileid);
2661         /* We don't change the creation time */
2662         WSET(server->packet, smb_vwv1, 0);
2663         WSET(server->packet, smb_vwv2, 0);
2664         date_unix2dos(server, fattr->f_atime, &date, &time);
2665         WSET(server->packet, smb_vwv3, date);
2666         WSET(server->packet, smb_vwv4, time);
2667         date_unix2dos(server, fattr->f_mtime, &date, &time);
2668         WSET(server->packet, smb_vwv5, date);
2669         WSET(server->packet, smb_vwv6, time);
2670 #ifdef SMBFS_DEBUG_TIMESTAMP
2671         printk(KERN_DEBUG "smb_proc_setattr_ext: date=%d, time=%d, mtime=%ld\n",
2672                date, time, fattr->f_mtime);
2673 #endif
2674
2675         result = smb_request_ok(server, SMBsetattrE, 0, 0);
2676         if (result < 0) {
2677                 if (smb_retry(server))
2678                         goto retry;
2679                 goto out;
2680         }
2681         result = 0;
2682 out:
2683         return result;
2684 }
2685
2686 /*
2687  * Note: called with the server locked.
2688  *
2689  * Bugs Noted:
2690  * (1) The TRANSACT2_SETPATHINFO message under Win NT 4.0 doesn't
2691  * set the file's attribute flags.
2692  */
2693 static int
2694 smb_proc_setattr_trans2(struct smb_sb_info *server,
2695                         struct dentry *dir, struct smb_fattr *fattr)
2696 {
2697         __u16 date, time;
2698         char *p, *param = server->temp_buf;
2699         unsigned char *resp_data = NULL;
2700         unsigned char *resp_param = NULL;
2701         int resp_data_len = 0;
2702         int resp_param_len = 0;
2703         int result;
2704         char data[26];
2705
2706       retry:
2707         WSET(param, 0, 1);      /* Info level SMB_INFO_STANDARD */
2708         DSET(param, 2, 0);
2709         result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
2710         if (result < 0)
2711                 goto out;
2712         p = param + 6 + result;
2713
2714         WSET(data, 0, 0); /* creation time */
2715         WSET(data, 2, 0);
2716         date_unix2dos(server, fattr->f_atime, &date, &time);
2717         WSET(data, 4, date);
2718         WSET(data, 6, time);
2719         date_unix2dos(server, fattr->f_mtime, &date, &time);
2720         WSET(data, 8, date);
2721         WSET(data, 10, time);
2722 #ifdef SMBFS_DEBUG_TIMESTAMP
2723         printk(KERN_DEBUG "setattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n", 
2724                DENTRY_PATH(dir), date, time, fattr->f_mtime);
2725 #endif
2726         DSET(data, 12, 0); /* size */
2727         DSET(data, 16, 0); /* blksize */
2728         WSET(data, 20, 0); /* attr */
2729         DSET(data, 22, 0); /* ULONG EA size */
2730
2731         result = smb_trans2_request(server, TRANSACT2_SETPATHINFO,
2732                                     26, data, p - param, param,
2733                                     &resp_data_len, &resp_data,
2734                                     &resp_param_len, &resp_param);
2735         if (result < 0)
2736         {
2737                 if (smb_retry(server))
2738                         goto retry;
2739                 goto out;
2740         }
2741         result = 0;
2742         if (server->rcls != 0)
2743                 result = smb_errno(server);
2744
2745 out:
2746         return result;
2747 }
2748
2749 /*
2750  * Set the modify and access timestamps for a file.
2751  *
2752  * Incredibly enough, in all of SMB there is no message to allow
2753  * setting both attributes and timestamps at once. 
2754  *
2755  * Bugs Noted:
2756  * (1) Win 95 doesn't support the TRANSACT2_SETFILEINFO message 
2757  * with info level 1 (INFO_STANDARD).
2758  * (2) Win 95 seems not to support setting directory timestamps.
2759  * (3) Under the core protocol apparently the only way to set the
2760  * timestamp is to open and close the file.
2761  */
2762 int
2763 smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
2764 {
2765         struct smb_sb_info *server = server_from_dentry(dentry);
2766         struct inode *inode = dentry->d_inode;
2767         int result;
2768
2769         VERBOSE("setting %s/%s, open=%d\n",
2770                 DENTRY_PATH(dentry), smb_is_open(inode));
2771
2772         smb_lock_server(server);
2773         /* setting the time on a Win95 server fails (tridge) */
2774         if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 && 
2775             !(server->mnt->flags & SMB_MOUNT_WIN95)) {
2776                 if (smb_is_open(inode) && SMB_I(inode)->access != SMB_O_RDONLY)
2777                         result = smb_proc_setattr_ext(server, inode, fattr);
2778                 else
2779                         result = smb_proc_setattr_trans2(server, dentry, fattr);
2780         } else {
2781                 /*
2782                  * Fail silently on directories ... timestamp can't be set?
2783                  */
2784                 result = 0;
2785                 if (S_ISREG(inode->i_mode)) {
2786                         /*
2787                          * Set the mtime by opening and closing the file.
2788                          * Note that the file is opened read-only, but this
2789                          * still allows us to set the date (tridge)
2790                          */
2791                         result = -EACCES;
2792                         if (!smb_is_open(inode))
2793                                 smb_proc_open(server, dentry, SMB_O_RDONLY);
2794                         if (smb_is_open(inode)) {
2795                                 inode->i_mtime = fattr->f_mtime;
2796                                 result = smb_proc_close_inode(server, inode);
2797                         }
2798                 }
2799         }
2800
2801         smb_unlock_server(server);
2802         return result;
2803 }
2804
2805 int
2806 smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
2807 {
2808         struct smb_sb_info *server = &(sb->u.smbfs_sb);
2809         int result;
2810         char *p;
2811         long unit;
2812
2813         smb_lock_server(server);
2814
2815       retry:
2816         smb_setup_header(server, SMBdskattr, 0, 0);
2817
2818         if ((result = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
2819                 if (smb_retry(server))
2820                         goto retry;
2821                 goto out;
2822         }
2823         p = SMB_VWV(server->packet);
2824         unit = (WVAL(p, 2) * WVAL(p, 4)) >> SMB_ST_BLKSHIFT;
2825         attr->f_blocks = WVAL(p, 0) * unit;
2826         attr->f_bsize  = SMB_ST_BLKSIZE;
2827         attr->f_bavail = attr->f_bfree = WVAL(p, 6) * unit;
2828         result = 0;
2829
2830 out:
2831         smb_unlock_server(server);
2832         return result;
2833 }
2834
2835
2836 static void
2837 install_ops(struct smb_ops *dst, struct smb_ops *src)
2838 {
2839         memcpy(dst, src, sizeof(void *) * SMB_OPS_NUM_STATIC);
2840 }
2841
2842 /* < LANMAN2 */
2843 static struct smb_ops smb_ops_core =
2844 {
2845         read:           smb_proc_read,
2846         write:          smb_proc_write,
2847         readdir:        smb_proc_readdir_short,
2848         getattr:        smb_proc_getattr_core,
2849         truncate:       smb_proc_trunc32,
2850 };
2851
2852 /* LANMAN2, OS/2, others? */
2853 static struct smb_ops smb_ops_os2 =
2854 {
2855         read:           smb_proc_read,
2856         write:          smb_proc_write,
2857         readdir:        smb_proc_readdir_long,
2858         getattr:        smb_proc_getattr_trans2_std,
2859         truncate:       smb_proc_trunc32,
2860 };
2861
2862 /* Win95, and possibly some NetApp versions too */
2863 static struct smb_ops smb_ops_win95 =
2864 {
2865         read:           smb_proc_read,  /* does not support 12word readX */
2866         write:          smb_proc_write,
2867         readdir:        smb_proc_readdir_long,
2868         getattr:        smb_proc_getattr_95,
2869         truncate:       smb_proc_trunc95,
2870 };
2871
2872 /* Samba, NT4 and NT5 */
2873 static struct smb_ops smb_ops_winNT =
2874 {
2875         read:           smb_proc_readX,
2876         write:          smb_proc_writeX,
2877         readdir:        smb_proc_readdir_long,
2878         getattr:        smb_proc_getattr_trans2_all,
2879         truncate:       smb_proc_trunc64,
2880 };