~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/smbfs/proc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.