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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [smbfs/] [proc.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  proc.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5
 *
6
 *  28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
7
 */
8
 
9
#include <linux/config.h>
10
#include <linux/fs.h>
11
#include <linux/smbno.h>
12
#include <linux/smb_fs.h>
13
#include <linux/types.h>
14
#include <linux/errno.h>
15
#include <linux/malloc.h>
16
#include <linux/stat.h>
17
#include <linux/fcntl.h>
18
#include <asm/segment.h>
19
#include <asm/string.h>
20
 
21
#define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
22
#define SMB_CMD(packet)  (BVAL(packet,8))
23
#define SMB_WCT(packet)  (BVAL(packet, SMB_HEADER_LEN - 1))
24
#define SMB_BCC(packet)  smb_bcc(packet)
25
#define SMB_BUF(packet)  ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
26
 
27
#define SMB_DIRINFO_SIZE 43
28
#define SMB_STATUS_SIZE  21
29
 
30
static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
31
 
32
static inline int
33
min(int a, int b)
34
{
35
        return a < b ? a : b;
36
}
37
 
38
static void
39
str_upper(char *name)
40
{
41
        while (*name)
42
        {
43
                if (*name >= 'a' && *name <= 'z')
44
                        *name -= ('a' - 'A');
45
                name++;
46
        }
47
}
48
 
49
static void
50
str_lower(char *name)
51
{
52
        while (*name)
53
        {
54
                if (*name >= 'A' && *name <= 'Z')
55
                        *name += ('a' - 'A');
56
                name++;
57
        }
58
}
59
 
60
/*****************************************************************************/
61
/*                                                                           */
62
/*  Encoding/Decoding section                                                */
63
/*                                                                           */
64
/*****************************************************************************/
65
 
66
static inline byte *
67
smb_decode_word(byte * p, word * data)
68
{
69
        *data = WVAL(p, 0);
70
        return p + 2;
71
}
72
 
73
byte *
74
smb_encode_smb_length(byte * p, dword len)
75
{
76
        BSET(p, 0, 0);
77
        BSET(p, 1, 0);
78
        BSET(p, 2, (len & 0xFF00) >> 8);
79
        BSET(p, 3, (len & 0xFF));
80
        if (len > 0xFFFF)
81
        {
82
                BSET(p, 1, 1);
83
        }
84
        return p + 4;
85
}
86
 
87
static byte *
88
smb_encode_ascii(byte * p, const byte * name, int len)
89
{
90
        *p++ = 4;
91
        strcpy(p, name);
92
        return p + len + 1;
93
}
94
 
95
static byte *
96
smb_encode_this_name(byte * p, const char *name, const int len)
97
{
98
        *p++ = '\\';
99
        strncpy(p, name, len);
100
        return p + len;
101
}
102
 
103
/* I put smb_encode_parents into a separate function so that the
104
   recursion only takes 16 bytes on the stack per path component on a
105
   386. */
106
 
107
static byte *
108
smb_encode_parents(byte * p, struct smb_inode_info *ino)
109
{
110
        byte *q;
111
 
112
        if (ino->dir == NULL)
113
        {
114
                return p;
115
        }
116
        q = smb_encode_parents(p, ino->dir);
117
        if (q - p + 1 + ino->finfo.len > SMB_MAXPATHLEN)
118
        {
119
                return p;
120
        }
121
        return smb_encode_this_name(q, ino->finfo.name, ino->finfo.len);
122
}
123
 
124
static byte *
125
smb_encode_path(struct smb_server *server,
126
                byte * p, struct smb_inode_info *dir,
127
                const char *name, const int len)
128
{
129
        byte *start = p;
130
        if (dir != NULL)
131
        {
132
                p = smb_encode_parents(p, dir);
133
        }
134
        p = smb_encode_this_name(p, name, len);
135
        *p++ = 0;
136
        if (server->protocol <= PROTOCOL_COREPLUS)
137
        {
138
                str_upper(start);
139
        }
140
        return p;
141
}
142
 
143
static byte *
144
smb_decode_data(byte * p, byte * data, word * data_len, int fs)
145
{
146
        word len;
147
 
148
        if (!(*p == 1 || *p == 5))
149
        {
150
                printk("smb_decode_data: Warning! Data block not starting "
151
                       "with 1 or 5\n");
152
        }
153
        len = WVAL(p, 1);
154
        p += 3;
155
 
156
        if (fs)
157
                memcpy_tofs(data, p, len);
158
        else
159
                memcpy(data, p, len);
160
 
161
        *data_len = len;
162
 
163
        return p + len;
164
}
165
 
166
static byte *
167
smb_name_mangle(byte * p, const byte * name)
168
{
169
        int len, pad = 0;
170
 
171
        len = strlen(name);
172
 
173
        if (len < 16)
174
                pad = 16 - len;
175
 
176
        *p++ = 2 * (len + pad);
177
 
178
        while (*name)
179
        {
180
                *p++ = (*name >> 4) + 'A';
181
                *p++ = (*name & 0x0F) + 'A';
182
                name++;
183
        }
184
        while (pad--)
185
        {
186
                *p++ = 'C';
187
                *p++ = 'A';
188
        }
189
        *p++ = '\0';
190
 
191
        return p;
192
}
193
 
194
/* The following are taken directly from msdos-fs */
195
 
196
/* Linear day numbers of the respective 1sts in non-leap years. */
197
 
198
static int day_n[] =
199
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
200
                  /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
201
 
202
 
203
extern struct timezone sys_tz;
204
 
205
static int
206
utc2local(int time)
207
{
208
        return time - sys_tz.tz_minuteswest * 60 + sys_tz.tz_dsttime * 3600;
209
}
210
 
211
static int
212
local2utc(int time)
213
{
214
        return time + sys_tz.tz_minuteswest * 60 - sys_tz.tz_dsttime * 3600;
215
}
216
 
217
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
218
 
219
static int
220
date_dos2unix(unsigned short time, unsigned short date)
221
{
222
        int month, year, secs;
223
 
224
        month = ((date >> 5) & 15) - 1;
225
        year = date >> 9;
226
        secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
227
            ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
228
                                                   month < 2 ? 1 : 0) + 3653);
229
        /* days since 1.1.70 plus 80's leap day */
230
        return local2utc(secs);
231
}
232
 
233
/*****************************************************************************/
234
/*                                                                           */
235
/*  Support section.                                                         */
236
/*                                                                           */
237
/*****************************************************************************/
238
 
239
dword
240
smb_len(byte * p)
241
{
242
        return ((BVAL(p, 1) & 0x1) << 16L) | (BVAL(p, 2) << 8L) | (BVAL(p, 3));
243
}
244
 
245
static word
246
smb_bcc(byte * packet)
247
{
248
        int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word);
249
        return WVAL(packet, pos);
250
}
251
 
252
/* smb_valid_packet: We check if packet fulfills the basic
253
   requirements of a smb packet */
254
 
255
static int
256
smb_valid_packet(byte * packet)
257
{
258
        DDPRINTK("len: %d, wct: %d, bcc: %d\n",
259
                 smb_len(packet), SMB_WCT(packet), SMB_BCC(packet));
260
        return (packet[4] == 0xff
261
                && packet[5] == 'S'
262
                && packet[6] == 'M'
263
                && packet[7] == 'B'
264
                && (smb_len(packet) + 4 == SMB_HEADER_LEN
265
                    + SMB_WCT(packet) * 2 + SMB_BCC(packet)));
266
}
267
 
268
/* smb_verify: We check if we got the answer we expected, and if we
269
   got enough data. If bcc == -1, we don't care. */
270
 
271
static int
272
smb_verify(byte * packet, int command, int wct, int bcc)
273
{
274
        return (SMB_CMD(packet) == command &&
275
                SMB_WCT(packet) >= wct &&
276
                (bcc == -1 || SMB_BCC(packet) >= bcc)) ? 0 : -EIO;
277
}
278
 
279
static int
280
smb_errno(int errcls, int error)
281
{
282
        if (errcls == ERRDOS)
283
                switch (error)
284
                {
285
                case ERRbadfunc:
286
                        return EINVAL;
287
                case ERRbadfile:
288
                        return ENOENT;
289
                case ERRbadpath:
290
                        return ENOENT;
291
                case ERRnofids:
292
                        return EMFILE;
293
                case ERRnoaccess:
294
                        return EACCES;
295
                case ERRbadfid:
296
                        return EBADF;
297
                case ERRbadmcb:
298
                        return EREMOTEIO;
299
                case ERRnomem:
300
                        return ENOMEM;
301
                case ERRbadmem:
302
                        return EFAULT;
303
                case ERRbadenv:
304
                        return EREMOTEIO;
305
                case ERRbadformat:
306
                        return EREMOTEIO;
307
                case ERRbadaccess:
308
                        return EACCES;
309
                case ERRbaddata:
310
                        return E2BIG;
311
                case ERRbaddrive:
312
                        return ENXIO;
313
                case ERRremcd:
314
                        return EREMOTEIO;
315
                case ERRdiffdevice:
316
                        return EXDEV;
317
                case ERRnofiles:
318
                        return 0;
319
                case ERRbadshare:
320
                        return ETXTBSY;
321
                case ERRlock:
322
                        return EDEADLK;
323
                case ERRfilexists:
324
                        return EEXIST;
325
                case 87:
326
                        return 0;        /* Unknown error!! */
327
                        /* This next error seems to occur on an mv when
328
                         * the destination exists */
329
                case 183:
330
                        return EEXIST;
331
                default:
332
                        return EIO;
333
        } else if (errcls == ERRSRV)
334
                switch (error)
335
                {
336
                case ERRerror:
337
                        return ENFILE;
338
                case ERRbadpw:
339
                        return EINVAL;
340
                case ERRbadtype:
341
                        return EIO;
342
                case ERRaccess:
343
                        return EACCES;
344
                default:
345
                        return EIO;
346
        } else if (errcls == ERRHRD)
347
                switch (error)
348
                {
349
                case ERRnowrite:
350
                        return EROFS;
351
                case ERRbadunit:
352
                        return ENODEV;
353
                case ERRnotready:
354
                        return EUCLEAN;
355
                case ERRbadcmd:
356
                        return EIO;
357
                case ERRdata:
358
                        return EIO;
359
                case ERRbadreq:
360
                        return ERANGE;
361
                case ERRbadshare:
362
                        return ETXTBSY;
363
                case ERRlock:
364
                        return EDEADLK;
365
                default:
366
                        return EIO;
367
        } else if (errcls == ERRCMD)
368
                return EIO;
369
        return 0;
370
}
371
 
372
static void
373
smb_lock_server(struct smb_server *server)
374
{
375
        while (server->lock)
376
                sleep_on(&server->wait);
377
        server->lock = 1;
378
}
379
 
380
static void
381
smb_unlock_server(struct smb_server *server)
382
{
383
        if (server->lock != 1)
384
        {
385
                printk("smb_unlock_server: was not locked!\n");
386
        }
387
        server->lock = 0;
388
        wake_up(&server->wait);
389
}
390
 
391
/* smb_request_ok: We expect the server to be locked. Then we do the
392
   request and check the answer completely. When smb_request_ok
393
   returns 0, you can be quite sure that everything went well. When
394
   the answer is <=0, the returned number is a valid unix errno. */
395
 
396
static int
397
smb_request_ok(struct smb_server *s, int command, int wct, int bcc)
398
{
399
        int result = 0;
400
        s->rcls = 0;
401
        s->err = 0;
402
 
403
        if (smb_request(s) < 0)
404
        {
405
                DPRINTK("smb_request failed\n");
406
                result = -EIO;
407
        } else if (smb_valid_packet(s->packet) != 0)
408
        {
409
                DPRINTK("not a valid packet!\n");
410
                result = -EIO;
411
        } else if (s->rcls != 0)
412
        {
413
                result = -smb_errno(s->rcls, s->err);
414
        } else if (smb_verify(s->packet, command, wct, bcc) != 0)
415
        {
416
                DPRINTK("smb_verify failed\n");
417
                result = -EIO;
418
        }
419
        return result;
420
}
421
 
422
/* smb_retry: This function should be called when smb_request_ok has
423
   indicated an error. If the error was indicated because the
424
   connection was killed, we try to reconnect. If smb_retry returns 0,
425
   the error was indicated for another reason, so a retry would not be
426
   of any use. */
427
 
428
static int
429
smb_retry(struct smb_server *server)
430
{
431
        if (server->state != CONN_INVALID)
432
        {
433
                return 0;
434
        }
435
        if (smb_release(server) < 0)
436
        {
437
                DPRINTK("smb_retry: smb_release failed\n");
438
                server->state = CONN_RETRIED;
439
                return 0;
440
        }
441
        if (smb_proc_reconnect(server) < 0)
442
        {
443
                DPRINTK("smb_proc_reconnect failed\n");
444
                server->state = CONN_RETRIED;
445
                return 0;
446
        }
447
        server->state = CONN_VALID;
448
        return 1;
449
}
450
 
451
static int
452
smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc)
453
{
454
        int result = smb_request_ok(s, command, wct, bcc);
455
 
456
        smb_unlock_server(s);
457
 
458
        return result;
459
}
460
 
461
/* smb_setup_header: We completely set up the packet. You only have to
462
   insert the command-specific fields */
463
 
464
__u8 *
465
smb_setup_header(struct smb_server * server, byte command, word wct, word bcc)
466
{
467
        dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2;
468
        byte *p = server->packet;
469
        byte *buf = server->packet;
470
 
471
        p = smb_encode_smb_length(p, xmit_len - 4);
472
 
473
        BSET(p, 0, 0xff);
474
        BSET(p, 1, 'S');
475
        BSET(p, 2, 'M');
476
        BSET(p, 3, 'B');
477
        BSET(p, 4, command);
478
 
479
        p += 5;
480
        memset(p, '\0', 19);
481
        p += 19;
482
        p += 8;
483
 
484
        WSET(buf, smb_tid, server->tid);
485
        WSET(buf, smb_pid, server->pid);
486
        WSET(buf, smb_uid, server->server_uid);
487
        WSET(buf, smb_mid, server->mid);
488
 
489
        if (server->protocol > PROTOCOL_CORE)
490
        {
491
                BSET(buf, smb_flg, 0x8);
492
                WSET(buf, smb_flg2, 0x3);
493
        }
494
        *p++ = wct;             /* wct */
495
        p += 2 * wct;
496
        WSET(p, 0, bcc);
497
        return p + 2;
498
}
499
 
500
/* smb_setup_header_exclusive waits on server->lock and locks the
501
   server, when it's free. You have to unlock it manually when you're
502
   finished with server->packet! */
503
 
504
static byte *
505
smb_setup_header_exclusive(struct smb_server *server,
506
                           byte command, word wct, word bcc)
507
{
508
        smb_lock_server(server);
509
        return smb_setup_header(server, command, wct, bcc);
510
}
511
 
512
static void
513
smb_setup_bcc(struct smb_server *server, byte * p)
514
{
515
        __u8 *packet = server->packet;
516
        __u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet);
517
        __u16 bcc = p - (pbcc + 2);
518
 
519
        WSET(pbcc, 0, bcc);
520
        smb_encode_smb_length(packet,
521
                              SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc);
522
}
523
 
524
 
525
/*****************************************************************************/
526
/*                                                                           */
527
/*  File operation section.                                                  */
528
/*                                                                           */
529
/*****************************************************************************/
530
 
531
int
532
smb_proc_open(struct smb_server *server,
533
              struct smb_inode_info *dir, const char *name, int len,
534
              struct smb_dirent *entry)
535
{
536
        int error;
537
        char *p;
538
        char *buf;
539
        const word o_attr = aSYSTEM | aHIDDEN | aDIR;
540
 
541
        DPRINTK("smb_proc_open: name=%s\n", name);
542
 
543
        smb_lock_server(server);
544
 
545
        if (entry->opened != 0)
546
        {
547
                /* Somebody else opened the file while we slept */
548
                smb_unlock_server(server);
549
                return 0;
550
        }
551
      retry:
552
        buf = server->packet;
553
        p = smb_setup_header(server, SMBopen, 2, 0);
554
        WSET(buf, smb_vwv0, 0x42);      /* read/write */
555
        WSET(buf, smb_vwv1, o_attr);
556
        *p++ = 4;
557
        p = smb_encode_path(server, p, dir, name, len);
558
        smb_setup_bcc(server, p);
559
 
560
        if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)
561
        {
562
 
563
                if (smb_retry(server))
564
                {
565
                        goto retry;
566
                }
567
                if ((error != -EACCES) && (error != -ETXTBSY)
568
                    && (error != -EROFS))
569
                {
570
                        smb_unlock_server(server);
571
                        return error;
572
                }
573
                /* N.B. Packet may change after request */
574
                buf = server->packet;
575
                p = smb_setup_header(server, SMBopen, 2, 0);
576
                WSET(buf, smb_vwv0, 0x40);      /* read only */
577
                WSET(buf, smb_vwv1, o_attr);
578
                *p++ = 4;
579
                p = smb_encode_path(server, p, dir, name, len);
580
                smb_setup_bcc(server, p);
581
 
582
                if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)
583
                {
584
                        if (smb_retry(server))
585
                        {
586
                                goto retry;
587
                        }
588
                        smb_unlock_server(server);
589
                        return error;
590
                }
591
        }
592
        /* We should now have data in vwv[0..6]. */
593
 
594
        /* N.B. Packet may change after request */
595
        buf = server->packet;
596
        entry->fileid = WVAL(buf, smb_vwv0);
597
        entry->attr = WVAL(buf, smb_vwv1);
598
        entry->f_ctime = entry->f_atime =
599
            entry->f_mtime = local2utc(DVAL(buf, smb_vwv2));
600
        entry->f_size = DVAL(buf, smb_vwv4);
601
        entry->access = WVAL(buf, smb_vwv6);
602
 
603
        entry->opened = 1;
604
        entry->access &= 3;
605
 
606
        smb_unlock_server(server);
607
 
608
        DPRINTK("smb_proc_open: entry->access = %d\n", entry->access);
609
        return 0;
610
}
611
 
612
int
613
smb_proc_close(struct smb_server *server,
614
               __u16 fileid, __u32 mtime)
615
{
616
        char *buf;
617
 
618
        smb_setup_header_exclusive(server, SMBclose, 3, 0);
619
        buf = server->packet;
620
        WSET(buf, smb_vwv0, fileid);
621
        DSET(buf, smb_vwv1, utc2local(mtime));
622
 
623
        return smb_request_ok_unlock(server, SMBclose, 0, 0);
624
}
625
 
626
/* In smb_proc_read and smb_proc_write we do not retry, because the
627
   file-id would not be valid after a reconnection. */
628
 
629
/* smb_proc_read: fs indicates if it should be copied with
630
   memcpy_tofs. */
631
 
632
int
633
smb_proc_read(struct smb_server *server, struct smb_dirent *finfo,
634
              off_t offset, long count, char *data, int fs)
635
{
636
        word returned_count, data_len;
637
        char *buf;
638
        int error;
639
 
640
        smb_setup_header_exclusive(server, SMBread, 5, 0);
641
        buf = server->packet;
642
 
643
        WSET(buf, smb_vwv0, finfo->fileid);
644
        WSET(buf, smb_vwv1, count);
645
        DSET(buf, smb_vwv2, offset);
646
        WSET(buf, smb_vwv4, 0);
647
 
648
        if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0)
649
        {
650
                smb_unlock_server(server);
651
                return error;
652
        }
653
        returned_count = WVAL(server->packet, smb_vwv0);
654
 
655
        smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs);
656
 
657
        smb_unlock_server(server);
658
 
659
        if (returned_count != data_len)
660
        {
661
                printk("smb_proc_read: Warning, returned_count != data_len\n");
662
                printk("smb_proc_read: ret_c=%d, data_len=%d\n",
663
                       returned_count, data_len);
664
        }
665
        return data_len;
666
}
667
 
668
int
669
smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
670
               off_t offset, int count, const char *data)
671
{
672
        int res = 0;
673
        char *buf;
674
        byte *p;
675
 
676
        p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3);
677
        buf = server->packet;
678
        WSET(buf, smb_vwv0, finfo->fileid);
679
        WSET(buf, smb_vwv1, count);
680
        DSET(buf, smb_vwv2, offset);
681
        WSET(buf, smb_vwv4, 0);
682
 
683
        *p++ = 1;
684
        WSET(p, 0, count);
685
        memcpy_fromfs(p + 2, data, count);
686
 
687
        if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0)
688
        {
689
                res = WVAL(server->packet, smb_vwv0);
690
        }
691
        smb_unlock_server(server);
692
 
693
        return res;
694
}
695
 
696
int
697
smb_proc_create(struct inode *dir, const char *name, int len,
698
                word attr, time_t ctime)
699
{
700
        int error;
701
        char *p;
702
        struct smb_server *server = SMB_SERVER(dir);
703
        char *buf;
704
        __u16 fileid;
705
 
706
        smb_lock_server(server);
707
      retry:
708
        buf = server->packet;
709
        p = smb_setup_header(server, SMBcreate, 3, 0);
710
        WSET(buf, smb_vwv0, attr);
711
        DSET(buf, smb_vwv1, utc2local(ctime));
712
        *p++ = 4;
713
        p = smb_encode_path(server, p, SMB_INOP(dir), name, len);
714
        smb_setup_bcc(server, p);
715
 
716
        if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0)
717
        {
718
                if (smb_retry(server))
719
                {
720
                        goto retry;
721
                }
722
                smb_unlock_server(server);
723
                return error;
724
        }
725
        fileid = WVAL(server->packet, smb_vwv0);
726
        smb_unlock_server(server);
727
 
728
        smb_proc_close(server, fileid, CURRENT_TIME);
729
 
730
        return 0;
731
}
732
 
733
int
734
smb_proc_mv(struct inode *odir, const char *oname, const int olen,
735
            struct inode *ndir, const char *nname, const int nlen)
736
{
737
        char *p;
738
        struct smb_server *server = SMB_SERVER(odir);
739
        int result;
740
 
741
        smb_lock_server(server);
742
 
743
      retry:
744
        p = smb_setup_header(server, SMBmv, 1, 0);
745
        WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
746
        *p++ = 4;
747
        p = smb_encode_path(server, p, SMB_INOP(odir), oname, olen);
748
        *p++ = 4;
749
        p = smb_encode_path(server, p, SMB_INOP(ndir), nname, nlen);
750
        smb_setup_bcc(server, p);
751
 
752
        if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0)
753
        {
754
                if (smb_retry(server))
755
                {
756
                        goto retry;
757
                }
758
        }
759
        smb_unlock_server(server);
760
        return result;
761
}
762
 
763
int
764
smb_proc_mkdir(struct inode *dir, const char *name, const int len)
765
{
766
        char *p;
767
        int result;
768
        struct smb_server *server = SMB_SERVER(dir);
769
 
770
        smb_lock_server(server);
771
 
772
      retry:
773
        p = smb_setup_header(server, SMBmkdir, 0, 0);
774
        *p++ = 4;
775
        p = smb_encode_path(server, p, SMB_INOP(dir), name, len);
776
        smb_setup_bcc(server, p);
777
 
778
        if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0)
779
        {
780
                if (smb_retry(server))
781
                {
782
                        goto retry;
783
                }
784
        }
785
        smb_unlock_server(server);
786
        return result;
787
}
788
 
789
int
790
smb_proc_rmdir(struct inode *dir, const char *name, const int len)
791
{
792
        char *p;
793
        int result;
794
        struct smb_server *server = SMB_SERVER(dir);
795
 
796
        smb_lock_server(server);
797
 
798
      retry:
799
        p = smb_setup_header(server, SMBrmdir, 0, 0);
800
        *p++ = 4;
801
        p = smb_encode_path(server, p, SMB_INOP(dir), name, len);
802
        smb_setup_bcc(server, p);
803
 
804
        if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0)
805
        {
806
                if (smb_retry(server))
807
                {
808
                        goto retry;
809
                }
810
        }
811
        smb_unlock_server(server);
812
        return result;
813
}
814
 
815
int
816
smb_proc_unlink(struct inode *dir, const char *name, const int len)
817
{
818
        char *p;
819
        struct smb_server *server = SMB_SERVER(dir);
820
        int result;
821
 
822
        smb_lock_server(server);
823
 
824
      retry:
825
        p = smb_setup_header(server, SMBunlink, 1, 0);
826
        WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
827
        *p++ = 4;
828
        p = smb_encode_path(server, p, SMB_INOP(dir), name, len);
829
        smb_setup_bcc(server, p);
830
 
831
        if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0)
832
        {
833
                if (smb_retry(server))
834
                {
835
                        goto retry;
836
                }
837
        }
838
        smb_unlock_server(server);
839
        return result;
840
}
841
 
842
int
843
smb_proc_trunc(struct smb_server *server, word fid, dword length)
844
{
845
        char *p;
846
        char *buf;
847
        int result;
848
 
849
        smb_lock_server(server);
850
 
851
      retry:
852
        buf = server->packet;
853
        p = smb_setup_header(server, SMBwrite, 5, 0);
854
        WSET(buf, smb_vwv0, fid);
855
        WSET(buf, smb_vwv1, 0);
856
        DSET(buf, smb_vwv2, length);
857
        WSET(buf, smb_vwv4, 0);
858
        p = smb_encode_ascii(p, "", 0);
859
        smb_setup_bcc(server, p);
860
 
861
        if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0)
862
        {
863
                if (smb_retry(server))
864
                {
865
                        goto retry;
866
                }
867
        }
868
        smb_unlock_server(server);
869
        return result;
870
}
871
 
872
static void
873
smb_init_dirent(struct smb_server *server, struct smb_dirent *entry)
874
{
875
        memset(entry, 0, sizeof(struct smb_dirent));
876
 
877
        entry->f_nlink = 1;
878
        entry->f_uid = server->m.uid;
879
        entry->f_gid = server->m.gid;
880
        entry->f_blksize = 512;
881
}
882
 
883
static void
884
smb_finish_dirent(struct smb_server *server, struct smb_dirent *entry)
885
{
886
        if ((entry->attr & aDIR) != 0)
887
        {
888
                entry->f_mode = server->m.dir_mode;
889
                entry->f_size = 512;
890
        } else
891
        {
892
                entry->f_mode = server->m.file_mode;
893
        }
894
 
895
        if (entry->attr & aRONLY)
896
                entry->f_mode &= ~0222;
897
 
898
        if ((entry->f_blksize != 0) && (entry->f_size != 0))
899
        {
900
                entry->f_blocks =
901
                    (entry->f_size - 1) / entry->f_blksize + 1;
902
        } else
903
        {
904
                entry->f_blocks = 0;
905
        }
906
        return;
907
}
908
 
909
void
910
smb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry)
911
{
912
        smb_init_dirent(server, entry);
913
        entry->attr = aDIR;
914
        entry->f_ino = 1;
915
        smb_finish_dirent(server, entry);
916
}
917
 
918
 
919
static char *
920
smb_decode_dirent(struct smb_server *server, char *p, struct smb_dirent *entry)
921
{
922
        smb_init_dirent(server, entry);
923
 
924
        p += SMB_STATUS_SIZE;   /* reserved (search_status) */
925
        entry->attr = BVAL(p, 0);
926
        entry->f_mtime = entry->f_atime = entry->f_ctime =
927
            date_dos2unix(WVAL(p, 1), WVAL(p, 3));
928
        entry->f_size = DVAL(p, 5);
929
        entry->len = strlen(p + 9);
930
        if (entry->len > 12)
931
        {
932
                entry->len = 12;
933
        }
934
        memcpy(entry->name, p + 9, entry->len);
935
        entry->name[entry->len] = '\0';
936
        while (entry->len > 2)
937
        {
938
                /* Pathworks fills names with spaces */
939
                entry->len -= 1;
940
                if (entry->name[entry->len] == ' ')
941
                {
942
                        entry->name[entry->len] = '\0';
943
                }
944
        }
945
        switch (server->case_handling)
946
        {
947
        case CASE_UPPER:
948
                str_upper(entry->name);
949
                break;
950
        case CASE_LOWER:
951
                str_lower(entry->name);
952
                break;
953
        default:
954
                break;
955
        }
956
        DPRINTK("smb_decode_dirent: name = %s\n", entry->name);
957
        smb_finish_dirent(server, entry);
958
        return p + 22;
959
}
960
 
961
/* This routine is used to read in directory entries from the network.
962
   Note that it is for short directory name seeks, i.e.: protocol <
963
   PROTOCOL_LANMAN2 */
964
 
965
static int
966
smb_proc_readdir_short(struct smb_server *server, struct inode *dir, int fpos,
967
                       int cache_size, struct smb_dirent *entry)
968
{
969
        char *p;
970
        char *buf;
971
        int error;
972
        int result;
973
        int i;
974
        int first, total_count;
975
        struct smb_dirent *current_entry;
976
        word bcc;
977
        word count;
978
        char status[SMB_STATUS_SIZE];
979
        int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE;
980
 
981
        DPRINTK("SMB call  readdir %d @ %d\n", cache_size, fpos);
982
 
983
        smb_lock_server(server);
984
 
985
      retry:
986
        buf = server->packet;
987
        first = 1;
988
        total_count = 0;
989
        current_entry = entry;
990
 
991
        while (1)
992
        {
993
                if (first == 1)
994
                {
995
                        p = smb_setup_header(server, SMBsearch, 2, 0);
996
                        WSET(buf, smb_vwv0, entries_asked);
997
                        WSET(buf, smb_vwv1, aDIR);
998
                        *p++ = 4;
999
                        p = smb_encode_path(server, p, SMB_INOP(dir), "*.*", 3);
1000
                        *p++ = 5;
1001
                        WSET(p, 0, 0);
1002
                        p += 2;
1003
                } else
1004
                {
1005
                        p = smb_setup_header(server, SMBsearch, 2, 0);
1006
                        WSET(buf, smb_vwv0, entries_asked);
1007
                        WSET(buf, smb_vwv1, aDIR);
1008
                        p = smb_encode_ascii(p, "", 0);
1009
                        *p++ = 5;
1010
                        WSET(p, 0, SMB_STATUS_SIZE);
1011
                        p += 2;
1012
                        memcpy(p, status, SMB_STATUS_SIZE);
1013
                        p += SMB_STATUS_SIZE;
1014
                }
1015
 
1016
                smb_setup_bcc(server, p);
1017
 
1018
                if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0)
1019
                {
1020
                        if ((server->rcls == ERRDOS)
1021
                            && (server->err == ERRnofiles))
1022
                        {
1023
                                result = total_count - fpos;
1024
                                goto unlock_return;
1025
                        } else
1026
                        {
1027
                                if (smb_retry(server))
1028
                                {
1029
                                        goto retry;
1030
                                }
1031
                                result = error;
1032
                                goto unlock_return;
1033
                        }
1034
                }
1035
                p = SMB_VWV(server->packet);
1036
                p = smb_decode_word(p, &count);
1037
                p = smb_decode_word(p, &bcc);
1038
 
1039
                first = 0;
1040
 
1041
                if (count <= 0)
1042
                {
1043
                        result = total_count - fpos;
1044
                        goto unlock_return;
1045
                }
1046
                if (bcc != count * SMB_DIRINFO_SIZE + 3)
1047
                {
1048
                        result = -EIO;
1049
                        goto unlock_return;
1050
                }
1051
                p += 3;         /* Skipping VBLOCK header
1052
                                   (5, length lo, length hi). */
1053
 
1054
                /* Read the last entry into the status field. */
1055
                memcpy(status,
1056
                       SMB_BUF(server->packet) + 3 +
1057
                       (count - 1) * SMB_DIRINFO_SIZE,
1058
                       SMB_STATUS_SIZE);
1059
 
1060
                /* Now we are ready to parse smb directory entries. */
1061
 
1062
                for (i = 0; i < count; i++)
1063
                {
1064
                        if (total_count < fpos)
1065
                        {
1066
                                p += SMB_DIRINFO_SIZE;
1067
                                DDPRINTK("smb_proc_readdir: skipped entry.\n");
1068
                                DDPRINTK("                  total_count = %d\n"
1069
                                         "                i = %d, fpos = %d\n",
1070
                                         total_count, i, fpos);
1071
                        } else if (total_count >= fpos + cache_size)
1072
                        {
1073
                                result = total_count - fpos;
1074
                                goto unlock_return;
1075
                        } else
1076
                        {
1077
                                p = smb_decode_dirent(server, p,
1078
                                                      current_entry);
1079
                                current_entry->f_pos = total_count;
1080
                                DDPRINTK("smb_proc_readdir: entry->f_pos = "
1081
                                         "%lu\n", entry->f_pos);
1082
                                current_entry += 1;
1083
                        }
1084
                        total_count += 1;
1085
                }
1086
        }
1087
      unlock_return:
1088
        smb_unlock_server(server);
1089
        return result;
1090
}
1091
 
1092
/* interpret a long filename structure - this is mostly guesses at the
1093
   moment.  The length of the structure is returned.  The structure of
1094
   a long filename depends on the info level. 260 is used by NT and 2
1095
   is used by OS/2. */
1096
 
1097
static char *
1098
smb_decode_long_dirent(struct smb_server *server, char *p,
1099
                       struct smb_dirent *entry, int level)
1100
{
1101
        char *result;
1102
 
1103
        smb_init_dirent(server, entry);
1104
 
1105
        switch (level)
1106
        {
1107
                /* We might add more levels later... */
1108
        case 1:
1109
                entry->len = BVAL(p, 26);
1110
                strncpy(entry->name, p + 27, entry->len);
1111
                entry->name[entry->len] = '\0';
1112
                entry->f_size = DVAL(p, 16);
1113
                entry->attr = BVAL(p, 24);
1114
 
1115
                entry->f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
1116
                entry->f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
1117
                entry->f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12));
1118
                result = p + 28 + BVAL(p, 26);
1119
                break;
1120
 
1121
        default:
1122
                DPRINTK("Unknown long filename format %d\n", level);
1123
                result = p + WVAL(p, 0);
1124
        }
1125
 
1126
        switch (server->case_handling)
1127
        {
1128
        case CASE_UPPER:
1129
                str_upper(entry->name);
1130
                break;
1131
        case CASE_LOWER:
1132
                str_lower(entry->name);
1133
                break;
1134
        default:
1135
                break;
1136
        }
1137
 
1138
        smb_finish_dirent(server, entry);
1139
        return result;
1140
}
1141
 
1142
int
1143
smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
1144
                      int cache_size, struct smb_dirent *cache)
1145
{
1146
        /* NT uses 260, OS/2 uses 2. Both accept 1. */
1147
        const int info_level = 1;
1148
        const int max_matches = 512;
1149
 
1150
        char *p;
1151
        char *lastname;
1152
        int lastname_len;
1153
        int i;
1154
        int first, entries, entries_seen;
1155
 
1156
        unsigned char *resp_data = NULL;
1157
        unsigned char *resp_param = NULL;
1158
        int resp_data_len = 0;
1159
        int resp_param_len = 0;
1160
 
1161
        __u16 command;
1162
 
1163
        int result;
1164
 
1165
        int ff_resume_key = 0;
1166
        int ff_searchcount = 0;
1167
        int ff_eos = 0;
1168
        int ff_lastname = 0;
1169
        int ff_dir_handle = 0;
1170
        int loop_count = 0;
1171
 
1172
        char param[SMB_MAXPATHLEN + 2 + 12];
1173
        int mask_len;
1174
        unsigned char *mask = &(param[12]);
1175
 
1176
        mask_len = smb_encode_path(server, mask,
1177
                                   SMB_INOP(dir), "*", 1) - mask;
1178
 
1179
        mask[mask_len] = 0;
1180
        mask[mask_len + 1] = 0;
1181
 
1182
        DPRINTK("smb_readdir_long cache=%d, fpos=%d, mask=%s\n",
1183
                cache_size, fpos, mask);
1184
 
1185
        smb_lock_server(server);
1186
 
1187
      retry:
1188
 
1189
        first = 1;
1190
        entries = 0;
1191
        entries_seen = 2;
1192
 
1193
        while (ff_eos == 0)
1194
        {
1195
                loop_count += 1;
1196
                if (loop_count > 200)
1197
                {
1198
                        printk("smb_proc_readdir_long: "
1199
                               "Looping in FIND_NEXT??\n");
1200
                        break;
1201
                }
1202
                if (first != 0)
1203
                {
1204
                        command = TRANSACT2_FINDFIRST;
1205
                        WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
1206
                        WSET(param, 2, max_matches);    /* max count */
1207
                        WSET(param, 4, 8 + 4 + 2);      /* resume required +
1208
                                                           close on end +
1209
                                                           continue */
1210
                        WSET(param, 6, info_level);
1211
                        DSET(param, 8, 0);
1212
                } else
1213
                {
1214
                        command = TRANSACT2_FINDNEXT;
1215
                        DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1216
                             ff_dir_handle, ff_resume_key, ff_lastname, mask);
1217
                        WSET(param, 0, ff_dir_handle);
1218
                        WSET(param, 2, max_matches);    /* max count */
1219
                        WSET(param, 4, info_level);
1220
                        DSET(param, 6, ff_resume_key);  /* ff_resume_key */
1221
                        WSET(param, 10, 8 + 4 + 2);     /* resume required +
1222
                                                           close on end +
1223
                                                           continue */
1224
                }
1225
#ifdef CONFIG_SMB_WIN95
1226
                /* Windows 95 is not able to deliver answers
1227
                   to FIND_NEXT fast enough, so sleep 0.2 seconds */
1228
                current->timeout = jiffies + HZ / 5;
1229
                current->state = TASK_INTERRUPTIBLE;
1230
                schedule();
1231
                current->timeout = 0;
1232
#endif
1233
 
1234
                result = smb_trans2_request(server, command,
1235
                                            0, NULL, 12 + mask_len + 2, param,
1236
                                            &resp_data_len, &resp_data,
1237
                                            &resp_param_len, &resp_param);
1238
 
1239
                if (result < 0)
1240
                {
1241
                        if (smb_retry(server))
1242
                        {
1243
                                goto retry;
1244
                        }
1245
                        DPRINTK("smb_proc_readdir_long: "
1246
                                "got error from trans2_request\n");
1247
                        break;
1248
                }
1249
                if (server->rcls != 0)
1250
                {
1251
                        result = -EIO;
1252
                        break;
1253
                }
1254
                /* parse out some important return info */
1255
                if (first != 0)
1256
                {
1257
                        ff_dir_handle = WVAL(resp_param, 0);
1258
                        ff_searchcount = WVAL(resp_param, 2);
1259
                        ff_eos = WVAL(resp_param, 4);
1260
                        ff_lastname = WVAL(resp_param, 8);
1261
                } else
1262
                {
1263
                        ff_searchcount = WVAL(resp_param, 0);
1264
                        ff_eos = WVAL(resp_param, 2);
1265
                        ff_lastname = WVAL(resp_param, 6);
1266
                }
1267
 
1268
                if (ff_searchcount == 0)
1269
                {
1270
                        break;
1271
                }
1272
                /* point to the data bytes */
1273
                p = resp_data;
1274
 
1275
                /* we might need the lastname for continuations */
1276
                lastname = "";
1277
                lastname_len = 0;
1278
                if (ff_lastname > 0)
1279
                {
1280
                        switch (info_level)
1281
                        {
1282
                        case 260:
1283
                                lastname = p + ff_lastname;
1284
                                lastname_len = resp_data_len - ff_lastname;
1285
                                ff_resume_key = 0;
1286
                                break;
1287
                        case 1:
1288
                                lastname = p + ff_lastname + 1;
1289
                                lastname_len = BVAL(p, ff_lastname);
1290
                                ff_resume_key = 0;
1291
                                break;
1292
                        }
1293
                }
1294
                lastname_len = min(lastname_len, 256);
1295
                strncpy(mask, lastname, lastname_len);
1296
                mask[lastname_len] = '\0';
1297
 
1298
                /* Now we are ready to parse smb directory entries. */
1299
 
1300
                for (i = 0; i < ff_searchcount; i++)
1301
                {
1302
                        struct smb_dirent *entry = &(cache[entries]);
1303
 
1304
                        p = smb_decode_long_dirent(server, p,
1305
                                                   entry, info_level);
1306
 
1307
                        DDPRINTK("smb_readdir_long: got %s\n", entry->name);
1308
 
1309
                        if ((entry->name[0] == '.')
1310
                            && ((entry->name[1] == '\0')
1311
                                || ((entry->name[1] == '.')
1312
                                    && (entry->name[2] == '\0'))))
1313
                        {
1314
                                /* ignore . and .. from the server */
1315
                                continue;
1316
                        }
1317
                        if (entries_seen >= fpos)
1318
                        {
1319
                                entry->f_pos = entries_seen;
1320
                                entries += 1;
1321
                        }
1322
                        if (entries >= cache_size)
1323
                        {
1324
                                goto finished;
1325
                        }
1326
                        entries_seen += 1;
1327
                }
1328
 
1329
                DPRINTK("received %d entries (eos=%d resume=%d)\n",
1330
                        ff_searchcount, ff_eos, ff_resume_key);
1331
 
1332
                first = 0;
1333
        }
1334
 
1335
      finished:
1336
        smb_unlock_server(server);
1337
        return entries;
1338
}
1339
 
1340
int
1341
smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos,
1342
                 int cache_size, struct smb_dirent *entry)
1343
{
1344
        if (server->protocol >= PROTOCOL_LANMAN2)
1345
                return smb_proc_readdir_long(server, dir, fpos, cache_size,
1346
                                             entry);
1347
        else
1348
                return smb_proc_readdir_short(server, dir, fpos, cache_size,
1349
                                              entry);
1350
}
1351
 
1352
/*
1353
 * This version uses the core protocol to get the attribute info.
1354
 * It works OK with Win 3.11, 95 and NT 3.51, but NOT with NT 4 (bad mtime).
1355
 */
1356
static int
1357
smb_proc_getattr_core(struct inode *dir, const char *name, int len,
1358
                      struct smb_dirent *entry)
1359
{
1360
        int result;
1361
        char *p;
1362
        struct smb_server *server = SMB_SERVER(dir);
1363
        char *buf;
1364
 
1365
        smb_lock_server(server);
1366
 
1367
        DDPRINTK("smb_proc_getattr_core: %s\n", name);
1368
 
1369
      retry:
1370
        buf = server->packet;
1371
        p = smb_setup_header(server, SMBgetatr, 0, 0);
1372
        *p++ = 4;
1373
        p = smb_encode_path(server, p, SMB_INOP(dir), name, len);
1374
        smb_setup_bcc(server, p);
1375
 
1376
        if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
1377
        {
1378
                if (smb_retry(server))
1379
                {
1380
                        goto retry;
1381
                }
1382
                smb_unlock_server(server);
1383
                return result;
1384
        }
1385
        /* N.B. Packet may change after request */
1386
        buf = server->packet;
1387
        entry->attr = WVAL(buf, smb_vwv0);
1388
        entry->f_ctime = entry->f_atime =
1389
            entry->f_mtime = local2utc(DVAL(buf, smb_vwv1));
1390
 
1391
        DDPRINTK("smb_proc_getattr_core: mtime=%ld\n", entry->f_mtime);
1392
 
1393
        entry->f_size = DVAL(buf, smb_vwv3);
1394
        smb_unlock_server(server);
1395
        return 0;
1396
}
1397
 
1398
/*
1399
 * This version uses the trans2 findfirst to get the attribute info.
1400
 * It works fine with NT 3.51 and NT 4 (any SP), but not with Win95 (ERRerror).
1401
 */
1402
static int
1403
smb_proc_getattr_ff(struct inode *dir, const char *name, int len,
1404
                    struct smb_dirent *entry)
1405
{
1406
        unsigned char *resp_data = NULL;
1407
        unsigned char *resp_param = NULL;
1408
        int resp_data_len = 0;
1409
        int resp_param_len = 0;
1410
 
1411
        char param[SMB_MAXPATHLEN + 1 + 12];
1412
        int mask_len;
1413
        unsigned char *mask = &(param[12]);
1414
 
1415
        int result;
1416
        char *p;
1417
        struct smb_server *server = SMB_SERVER(dir);
1418
 
1419
        mask_len = smb_encode_path(server, mask,
1420
                                   SMB_INOP(dir), name, len) - mask;
1421
 
1422
        mask[mask_len] = 0;
1423
 
1424
        DDPRINTK("smb_proc_getattr_ff: mask=%s\n", mask);
1425
 
1426
        smb_lock_server(server);
1427
 
1428
      retry:
1429
 
1430
        WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
1431
        WSET(param, 2, 1);      /* max count */
1432
        WSET(param, 4, 2 + 1);  /* close on end + close after this call */
1433
        WSET(param, 6, 1);      /* info level */
1434
        DSET(param, 8, 0);
1435
 
1436
        result = smb_trans2_request(server, TRANSACT2_FINDFIRST,
1437
                                    0, NULL, 12 + mask_len + 1, param,
1438
                                    &resp_data_len, &resp_data,
1439
                                    &resp_param_len, &resp_param);
1440
 
1441
        if (result < 0)
1442
        {
1443
                if (smb_retry(server))
1444
                {
1445
                        DPRINTK("smb_proc_getattr_ff: error=%d, retrying\n",
1446
                                 result);
1447
                        goto retry;
1448
                }
1449
                goto out;
1450
        }
1451
        if (server->rcls != 0)
1452
        {
1453
                result = -smb_errno(server->rcls, server->err);
1454
                if (result != -ENOENT)
1455
                        DPRINTK("smb_proc_getattr_ff: rcls=%d, err=%d\n",
1456
                                 server->rcls, server->err);
1457
                goto out;
1458
        }
1459
        /* Make sure we got enough data ... */
1460
        result = -EINVAL;      /* WVAL(resp_param, 2) is ff_searchcount */
1461
        if (resp_data_len < 22 || WVAL(resp_param, 2) != 1)
1462
        {
1463
                DPRINTK("smb_proc_getattr_ff: bad result, len=%d, count=%d\n",
1464
                         resp_data_len, WVAL(resp_param, 2));
1465
                goto out;
1466
        }
1467
        /* Decode the response (info level 1, as in smb_decode_long_dirent) */
1468
        p = resp_data;
1469
        entry->f_ctime = date_dos2unix(WVAL(p, 2), WVAL(p, 0));
1470
        entry->f_atime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
1471
        entry->f_mtime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
1472
        entry->f_size = DVAL(p, 12);
1473
        entry->attr = WVAL(p, 20);
1474
 
1475
        DDPRINTK("smb_proc_getattr_ff: attr=%x\n", entry->attr);
1476
 
1477
        result = 0;
1478
 
1479
out:
1480
        smb_unlock_server(server);
1481
        return result;
1482
}
1483
 
1484
int
1485
smb_proc_getattr(struct inode *dir, const char *name, int len,
1486
                 struct smb_dirent *entry)
1487
{
1488
        struct smb_server *server = SMB_SERVER(dir);
1489
        int result;
1490
 
1491
        smb_init_dirent(server, entry);
1492
 
1493
        /* Use trans2 for NT, use core protocol for others (Win95/3.11/...).
1494
         * We distinguish NT from Win95 by looking at the capabilities,
1495
         * in the same way as in Samba 1.9.18p2's reply.c.
1496
         */
1497
        if ((server->protocol >= PROTOCOL_LANMAN2)
1498
            && (server->blkmode & (CAP_NT_SMBS | CAP_STATUS32)))
1499
                result = smb_proc_getattr_ff(dir, name, len, entry);
1500
        else
1501
                result = smb_proc_getattr_core(dir, name, len, entry);
1502
 
1503
        smb_finish_dirent(server, entry);
1504
 
1505
        entry->len = len;
1506
        memcpy(entry->name, name, len);
1507
        /* entry->name is null terminated from smb_init_dirent */
1508
 
1509
        return result;
1510
}
1511
 
1512
int
1513
smb_proc_setattr(struct smb_server *server,
1514
                 struct inode *i, struct smb_dirent *new_finfo)
1515
{
1516
        char *p;
1517
        char *buf;
1518
        int result;
1519
 
1520
        smb_lock_server(server);
1521
 
1522
      retry:
1523
        buf = server->packet;
1524
        p = smb_setup_header(server, SMBsetatr, 8, 0);
1525
        WSET(buf, smb_vwv0, new_finfo->attr);
1526
        DSET(buf, smb_vwv1, 0);
1527
        DSET(buf, smb_vwv3, 0);
1528
        DSET(buf, smb_vwv5, 0);
1529
        WSET(buf, smb_vwv7, 0);
1530
        *p++ = 4;
1531
        p = smb_encode_path(server, p,
1532
                            SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name,
1533
                            SMB_INOP(i)->finfo.len);
1534
 
1535
        smb_setup_bcc(server, p);
1536
        if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0)
1537
        {
1538
                if (smb_retry(server))
1539
                {
1540
                        goto retry;
1541
                }
1542
        }
1543
        smb_unlock_server(server);
1544
        return result;
1545
}
1546
 
1547
int
1548
smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr)
1549
{
1550
        int error;
1551
        char *p;
1552
        struct smb_server *server = &(SMB_SBP(super)->s_server);
1553
 
1554
        smb_lock_server(server);
1555
 
1556
      retry:
1557
        smb_setup_header(server, SMBdskattr, 0, 0);
1558
 
1559
        if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0)
1560
        {
1561
                if (smb_retry(server))
1562
                {
1563
                        goto retry;
1564
                }
1565
                smb_unlock_server(server);
1566
                return error;
1567
        }
1568
        p = SMB_VWV(server->packet);
1569
        p = smb_decode_word(p, &attr->total);
1570
        p = smb_decode_word(p, &attr->allocblocks);
1571
        p = smb_decode_word(p, &attr->blocksize);
1572
        p = smb_decode_word(p, &attr->free);
1573
        smb_unlock_server(server);
1574
        return 0;
1575
}
1576
 
1577
/*****************************************************************************/
1578
/*                                                                           */
1579
/*  Mount/umount operations.                                                 */
1580
/*                                                                           */
1581
/*****************************************************************************/
1582
 
1583
struct smb_prots
1584
{
1585
        enum smb_protocol prot;
1586
        const char *name;
1587
};
1588
 
1589
/* smb_proc_reconnect: We expect the server to be locked, so that you
1590
   can call the routine from within smb_retry. The socket must be
1591
   created, like after a user-level socket()-call. It may not be
1592
   connected. */
1593
 
1594
int
1595
smb_proc_reconnect(struct smb_server *server)
1596
{
1597
        struct smb_prots prots[] =
1598
        {
1599
                {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
1600
                {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
1601
#ifdef LANMAN1
1602
                {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
1603
                {PROTOCOL_LANMAN1, "LANMAN1.0"},
1604
#endif
1605
#ifdef LANMAN2
1606
                {PROTOCOL_LANMAN2, "LM1.2X002"},
1607
#endif
1608
#ifdef NT1
1609
                {PROTOCOL_NT1, "NT LM 0.12"},
1610
                {PROTOCOL_NT1, "NT LANMAN 1.0"},
1611
#endif
1612
                {-1, NULL}};
1613
        char dev[] = "A:";
1614
        int i, plength;
1615
        int max_xmit = 1024;    /* Space needed for first request. */
1616
        int given_max_xmit = server->m.max_xmit;
1617
        int result;
1618
        byte *p;
1619
 
1620
        if ((result = smb_connect(server)) < 0)
1621
        {
1622
                DPRINTK("smb_proc_reconnect: could not smb_connect\n");
1623
                goto fail;
1624
        }
1625
        /* Here we assume that the connection is valid */
1626
        server->state = CONN_VALID;
1627
 
1628
        if (server->packet != NULL)
1629
        {
1630
                smb_vfree(server->packet);
1631
                server->packet = NULL;
1632
                server->packet_size = 0;
1633
        }
1634
        server->packet = smb_vmalloc(max_xmit);
1635
 
1636
        if (server->packet == NULL)
1637
        {
1638
                printk("smb_proc_connect: No memory! Bailing out.\n");
1639
                result = -ENOMEM;
1640
                goto fail;
1641
        }
1642
        server->packet_size = server->max_xmit = max_xmit;
1643
 
1644
        /*
1645
         * Start with an RFC1002 session request packet.
1646
         */
1647
        p = server->packet + 4;
1648
 
1649
        p = smb_name_mangle(p, server->m.server_name);
1650
        p = smb_name_mangle(p, server->m.client_name);
1651
 
1652
        smb_encode_smb_length(server->packet,
1653
                              (void *) p - (void *) (server->packet));
1654
 
1655
        server->packet[0] = 0x81;        /* SESSION REQUEST */
1656
 
1657
        if (smb_catch_keepalive(server) < 0)
1658
        {
1659
                printk("smb_proc_connect: could not catch_keepalives\n");
1660
        }
1661
        if ((result = smb_request(server)) < 0)
1662
        {
1663
                DPRINTK("smb_proc_connect: Failed to send SESSION REQUEST.\n");
1664
                smb_dont_catch_keepalive(server);
1665
                goto fail;
1666
        }
1667
        if (server->packet[0] != 0x82)
1668
        {
1669
                printk("smb_proc_connect: Did not receive positive response "
1670
                       "(err = %x)\n",
1671
                       server->packet[0]);
1672
                smb_dont_catch_keepalive(server);
1673
                result = -EIO;
1674
                goto fail;
1675
        }
1676
        DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n");
1677
 
1678
        /* Now we are ready to send a SMB Negotiate Protocol packet. */
1679
        memset(server->packet, 0, SMB_HEADER_LEN);
1680
 
1681
        plength = 0;
1682
        for (i = 0; prots[i].name != NULL; i++)
1683
        {
1684
                plength += strlen(prots[i].name) + 2;
1685
        }
1686
 
1687
        smb_setup_header(server, SMBnegprot, 0, plength);
1688
 
1689
        p = SMB_BUF(server->packet);
1690
 
1691
        for (i = 0; prots[i].name != NULL; i++)
1692
        {
1693
                *p++ = 2;
1694
                strcpy(p, prots[i].name);
1695
                p += strlen(prots[i].name) + 1;
1696
        }
1697
 
1698
        if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0)
1699
        {
1700
                DPRINTK("smb_proc_connect: Failure requesting SMBnegprot\n");
1701
                smb_dont_catch_keepalive(server);
1702
                goto fail;
1703
        } else
1704
        {
1705
                DDPRINTK("smb_proc_connect: Request SMBnegprot..");
1706
        }
1707
 
1708
        DDPRINTK("Verified!\n");
1709
 
1710
        p = SMB_VWV(server->packet);
1711
        p = smb_decode_word(p, (word *) & i);
1712
#ifdef CONFIG_COLDFIRE
1713
        /*
1714
         *      Not quite sure why this is needed???
1715
         *      Maybe the byte swapping code is broken, but the result
1716
         *      byte is certainly in the wrong position within the word.
1717
         */
1718
        i = i >> 16;
1719
#endif
1720
        server->protocol = prots[i].prot;
1721
 
1722
        DPRINTK("smb_proc_connect: Server wants %s protocol.\n",
1723
                prots[i].name);
1724
 
1725
        if (server->protocol >= PROTOCOL_LANMAN1)
1726
        {
1727
 
1728
                word passlen = strlen(server->m.password);
1729
                word userlen = strlen(server->m.username);
1730
 
1731
#ifdef DEBUG_SMB_PASSWORD
1732
                DPRINTK("smb_proc_connect: password = %s\n",
1733
                        server->m.password);
1734
#endif                  
1735
                DPRINTK("smb_proc_connect: usernam = %s\n",
1736
                        server->m.username);
1737
 
1738
                if (server->protocol >= PROTOCOL_NT1)
1739
                {
1740
                        server->max_xmit = DVAL(server->packet, smb_vwv3 + 1);
1741
                        server->maxmux = WVAL(server->packet, smb_vwv1 + 1);
1742
                        server->maxvcs = WVAL(server->packet, smb_vwv2 + 1);
1743
                        server->blkmode = DVAL(server->packet, smb_vwv9 + 1);
1744
                        server->sesskey = DVAL(server->packet, smb_vwv7 + 1);
1745
                } else
1746
                {
1747
                        server->max_xmit = WVAL(server->packet, smb_vwv2);
1748
                        server->maxmux = WVAL(server->packet, smb_vwv3);
1749
                        server->maxvcs = WVAL(server->packet, smb_vwv4);
1750
                        server->blkmode = WVAL(server->packet, smb_vwv5);
1751
                        server->sesskey = DVAL(server->packet, smb_vwv6);
1752
                }
1753
                DPRINTK("smb_proc_connect: blkmode (capabilities) = %x\n",
1754
                        server->blkmode);
1755
 
1756
                if (server->max_xmit < given_max_xmit)
1757
                {
1758
                        /* We do not distinguish between the client
1759
                           requests and the server response. */
1760
                        given_max_xmit = server->max_xmit;
1761
                }
1762
                if (server->protocol >= PROTOCOL_NT1)
1763
                {
1764
                        char *workgroup = server->m.domain;
1765
                        char *OS_id = "Unix";
1766
                        char *client_id = "ksmbfs";
1767
 
1768
                        smb_setup_header(server, SMBsesssetupX, 13,
1769
                                         5 + userlen + passlen +
1770
                                         strlen(workgroup) + strlen(OS_id) +
1771
                                         strlen(client_id));
1772
 
1773
                        WSET(server->packet, smb_vwv0, 0x00ff);
1774
                        WSET(server->packet, smb_vwv1, 0);
1775
                        WSET(server->packet, smb_vwv2, given_max_xmit);
1776
                        WSET(server->packet, smb_vwv3, 2);
1777
                        WSET(server->packet, smb_vwv4, server->pid);
1778
                        DSET(server->packet, smb_vwv5, server->sesskey);
1779
                        WSET(server->packet, smb_vwv7, passlen + 1);
1780
                        WSET(server->packet, smb_vwv8, 0);
1781
                        WSET(server->packet, smb_vwv9, 0);
1782
 
1783
                        p = SMB_BUF(server->packet);
1784
                        strcpy(p, server->m.password);
1785
                        p += passlen + 1;
1786
                        strcpy(p, server->m.username);
1787
                        p += userlen + 1;
1788
                        strcpy(p, workgroup);
1789
                        p += strlen(p) + 1;
1790
                        strcpy(p, OS_id);
1791
                        p += strlen(p) + 1;
1792
                        strcpy(p, client_id);
1793
                } else
1794
                {
1795
                        smb_setup_header(server, SMBsesssetupX, 10,
1796
                                         2 + userlen + passlen);
1797
 
1798
                        WSET(server->packet, smb_vwv0, 0x00ff);
1799
                        WSET(server->packet, smb_vwv1, 0);
1800
                        WSET(server->packet, smb_vwv2, given_max_xmit);
1801
                        WSET(server->packet, smb_vwv3, 2);
1802
                        WSET(server->packet, smb_vwv4, server->pid);
1803
                        DSET(server->packet, smb_vwv5, server->sesskey);
1804
                        WSET(server->packet, smb_vwv7, passlen + 1);
1805
                        WSET(server->packet, smb_vwv8, 0);
1806
                        WSET(server->packet, smb_vwv9, 0);
1807
 
1808
                        p = SMB_BUF(server->packet);
1809
                        strcpy(p, server->m.password);
1810
                        p += passlen + 1;
1811
                        strcpy(p, server->m.username);
1812
                }
1813
 
1814
                if ((result = smb_request_ok(server, SMBsesssetupX, 3, 0)) < 0)
1815
                {
1816
                        DPRINTK("smb_proc_connect: SMBsessetupX failed\n");
1817
                        smb_dont_catch_keepalive(server);
1818
                        goto fail;
1819
                }
1820
                smb_decode_word(server->packet + 32, &(server->server_uid));
1821
        } else
1822
        {
1823
                server->max_xmit = 0;
1824
                server->maxmux = 0;
1825
                server->maxvcs = 0;
1826
                server->blkmode = 0;
1827
                server->sesskey = 0;
1828
        }
1829
 
1830
        /* Fine! We have a connection, send a tcon message. */
1831
 
1832
        smb_setup_header(server, SMBtcon, 0,
1833
                         6 + strlen(server->m.service) +
1834
                         strlen(server->m.password) + strlen(dev));
1835
 
1836
        p = SMB_BUF(server->packet);
1837
        p = smb_encode_ascii(p, server->m.service, strlen(server->m.service));
1838
        p = smb_encode_ascii(p, server->m.password, strlen(server->m.password));
1839
        p = smb_encode_ascii(p, dev, strlen(dev));
1840
 
1841
        if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0)
1842
        {
1843
                DPRINTK("smb_proc_connect: SMBtcon not verified.\n");
1844
                smb_dont_catch_keepalive(server);
1845
                goto fail;
1846
        }
1847
        DDPRINTK("OK! Managed to set up SMBtcon!\n");
1848
 
1849
        p = SMB_VWV(server->packet);
1850
 
1851
        if (server->protocol <= PROTOCOL_COREPLUS)
1852
        {
1853
                word max_xmit;
1854
 
1855
                p = smb_decode_word(p, &max_xmit);
1856
                server->max_xmit = max_xmit;
1857
 
1858
                if (server->max_xmit > given_max_xmit)
1859
                {
1860
                        server->max_xmit = given_max_xmit;
1861
                }
1862
        } else
1863
        {
1864
                p += 2;
1865
        }
1866
 
1867
        p = smb_decode_word(p, &server->tid);
1868
 
1869
        /* Ok, everything is fine. max_xmit does not include */
1870
        /* the TCP-SMB header of 4 bytes. */
1871
        server->max_xmit += 4;
1872
 
1873
        DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid);
1874
 
1875
        /* Now make a new packet with the correct size. */
1876
        smb_vfree(server->packet);
1877
        server->packet = NULL;
1878
 
1879
        server->packet = smb_vmalloc(server->max_xmit);
1880
        if (server->packet == NULL)
1881
        {
1882
                printk("smb_proc_connect: No memory left in end of "
1883
                       "connection phase :-(\n");
1884
                smb_dont_catch_keepalive(server);
1885
                goto fail;
1886
        }
1887
        server->packet_size = server->max_xmit;
1888
 
1889
        DPRINTK("smb_proc_connect: Normal exit\n");
1890
        return 0;
1891
 
1892
      fail:
1893
        server->state = CONN_INVALID;
1894
        return result;
1895
}
1896
 
1897
/* smb_proc_reconnect: server->packet is allocated with
1898
   server->max_xmit bytes if and only if we return >= 0 */
1899
int
1900
smb_proc_connect(struct smb_server *server)
1901
{
1902
        int result;
1903
        smb_lock_server(server);
1904
 
1905
        result = smb_proc_reconnect(server);
1906
 
1907
        if ((result < 0) && (server->packet != NULL))
1908
        {
1909
                smb_vfree(server->packet);
1910
                server->packet = NULL;
1911
        }
1912
        smb_unlock_server(server);
1913
        return result;
1914
}
1915
 
1916
int
1917
smb_proc_disconnect(struct smb_server *server)
1918
{
1919
        smb_setup_header_exclusive(server, SMBtdis, 0, 0);
1920
        return smb_request_ok_unlock(server, SMBtdis, 0, 0);
1921
}

powered by: WebSVN 2.1.0

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