OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [smbfs/] [proc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.