source: trunk/samba-3.0.25pre1/source/ndpsmb/smbwrp.c@ 5

Last change on this file since 5 was 5, checked in by Yuri Dario, 18 years ago

OS/2 client code, initial import.

  • Property svn:eol-style set to native
File size: 36.6 KB
Line 
1#include "includes.h"
2
3#include "smbwrp.h"
4
5/*
6 * Wrapper for cli_errno to return not connected error on negative fd
7 */
8int os2cli_errno(cli_state * cli)
9{
10 if (cli->fd == -1)
11 {
12 return ENOTCONN;
13 }
14 return cli_errno(cli);
15}
16
17int _System smbwrp_getclisize(void)
18{
19 return sizeof(struct cli_state);
20}
21
22/*****************************************************
23initialise structures
24*******************************************************/
25int _System smbwrp_init(void)
26{
27 static int initialised = 0;
28 char *p;
29 pstring line;
30
31 if (initialised)
32 {
33 return 0;
34 }
35 initialised = 1;
36
37 init_globals();
38
39 load_interfaces();
40
41 if (!init_names())
42 {
43 return 1;
44 }
45
46/*
47 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
48 lp_set_name_resolve_order(p);
49 }
50*/
51 return 0;
52
53}
54
55#if 0
56/*****************************************************
57remove redundent stuff from a filename
58*******************************************************/
59void clean_fname(char *name)
60{
61 char *p, *p2;
62 int l;
63 int modified = 1;
64
65 if (!name) return;
66
67 while (modified) {
68 modified = 0;
69
70 if ((p=strstr(name,"/./"))) {
71 modified = 1;
72 while (*p) {
73 p[0] = p[2];
74 p++;
75 }
76 }
77
78 if ((p=strstr(name,"//"))) {
79 modified = 1;
80 while (*p) {
81 p[0] = p[1];
82 p++;
83 }
84 }
85
86 if (strcmp(name,"/../")==0) {
87 modified = 1;
88 name[1] = 0;
89 }
90
91 if ((p=strstr(name,"/../"))) {
92 modified = 1;
93 for (p2=(p>name?p-1:p);p2>name;p2--) {
94 if (p2[0] == '/') break;
95 }
96 while (*p2) {
97 p2[0] = p2[3];
98 p2++;
99 }
100 }
101
102 if (strcmp(name,"/..")==0) {
103 modified = 1;
104 name[1] = 0;
105 }
106
107 l = strlen(name);
108 p = l>=3?(name+l-3):name;
109 if (strcmp(p,"/..")==0) {
110 modified = 1;
111 for (p2=p-1;p2>name;p2--) {
112 if (p2[0] == '/') break;
113 }
114 if (p2==name) {
115 p[0] = '/';
116 p[1] = 0;
117 } else {
118 p2[0] = 0;
119 }
120 }
121
122 l = strlen(name);
123 p = l>=2?(name+l-2):name;
124 if (strcmp(p,"/.")==0) {
125 if (p == name) {
126 p[1] = 0;
127 } else {
128 p[0] = 0;
129 }
130 }
131
132 if (strncmp(p=name,"./",2) == 0) {
133 modified = 1;
134 do {
135 p[0] = p[2];
136 } while (*p++);
137 }
138
139 l = strlen(p=name);
140 if (l > 1 && p[l-1] == '/') {
141 modified = 1;
142 p[l-1] = 0;
143 }
144 }
145}
146#endif
147
148
149/****************************************************************************
150send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
151****************************************************************************/
152BOOL cli_qpathinfo3(struct cli_state *cli, const char *fname,
153 time_t *c_time, time_t *a_time, time_t *m_time,
154 time_t *w_time, off_t *size, uint16 *mode,
155 SMB_INO_T *ino)
156{
157 unsigned int data_len = 0;
158 unsigned int param_len = 0;
159 uint16 setup = TRANSACT2_QPATHINFO;
160 pstring param;
161 char *rparam=NULL, *rdata=NULL;
162 char *p;
163
164 p = param;
165 memset(p, 0, 6);
166 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
167 p += 6;
168 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
169
170 param_len = PTR_DIFF(p, param);
171
172 if (!cli_send_trans(cli, SMBtrans2,
173 NULL, /* name */
174 -1, 0, /* fid, flags */
175 &setup, 1, 0, /* setup, length, max */
176 param, param_len, 10, /* param, length, max */
177 NULL, data_len, cli->max_xmit /* data, length, max */
178 )) {
179 return False;
180 }
181
182 if (!cli_receive_trans(cli, SMBtrans2,
183 &rparam, &param_len,
184 &rdata, &data_len)) {
185 return False;
186 }
187
188 if (!rdata || data_len < 22) {
189 return False;
190 }
191
192 if (c_time) {
193 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
194 }
195 if (a_time) {
196 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
197 }
198 if (m_time) {
199 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
200 }
201 if (w_time) {
202 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
203 }
204 if (mode) {
205 *mode = SVAL(rdata, 32);
206 }
207 if (size) {
208 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
209 }
210 if (ino) {
211 *ino = IVAL(rdata, 64);
212 }
213
214 SAFE_FREE(rdata);
215 SAFE_FREE(rparam);
216 return True;
217}
218
219/****************************************************************************
220send a qfileinfo call
221****************************************************************************/
222BOOL cli_qfileinfo3(struct cli_state *cli, int fnum,
223 uint16 *mode, off_t *size,
224 time_t *c_time, time_t *a_time, time_t *m_time,
225 time_t *w_time, SMB_INO_T *ino)
226{
227 unsigned int data_len = 0;
228 unsigned int param_len = 0;
229 uint16 setup = TRANSACT2_QFILEINFO;
230 pstring param;
231 char *rparam=NULL, *rdata=NULL;
232
233 /* if its a win95 server then fail this - win95 totally screws it
234 up */
235 if (cli->win95) return False;
236
237 param_len = 4;
238
239 memset(param, 0, param_len);
240 SSVAL(param, 0, fnum);
241 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
242
243 if (!cli_send_trans(cli, SMBtrans2,
244 NULL, /* name */
245 -1, 0, /* fid, flags */
246 &setup, 1, 0, /* setup, length, max */
247 param, param_len, 2, /* param, length, max */
248 NULL, data_len, cli->max_xmit /* data, length, max */
249 )) {
250 return False;
251 }
252
253 if (!cli_receive_trans(cli, SMBtrans2,
254 &rparam, &param_len,
255 &rdata, &data_len)) {
256 return False;
257 }
258
259 if (!rdata || data_len < 68) {
260 return False;
261 }
262
263 if (c_time) {
264 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
265 }
266 if (a_time) {
267 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
268 }
269 if (m_time) {
270 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
271 }
272 if (w_time) {
273 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
274 }
275 if (mode) {
276 *mode = SVAL(rdata, 32);
277 }
278 if (size) {
279 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
280 }
281 if (ino) {
282 *ino = IVAL(rdata, 64);
283 }
284
285 SAFE_FREE(rdata);
286 SAFE_FREE(rparam);
287 return True;
288}
289
290/*****************************************************
291return a connection to a server
292*******************************************************/
293int _System smbwrp_connect(smbwrp_server * srv, cli_state * c)
294{
295 char * server = srv->server_name;
296 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
297 char * workgroup = srv->workgroup;
298 struct nmb_name called, calling;
299 char *p, *server_n = server;
300 fstring group;
301 struct in_addr ip;
302 int rc;
303
304 zero_ip(&ip);
305 ZERO_STRUCTP(c);
306
307 DEBUG(1,("Connecting to \\\\%s:%s@%s:%s\\%s. Master %s:%d\n", srv->username, srv->password, workgroup, server, share, srv->master, srv->ifmastergroup));
308
309 if (!*server) {
310 struct in_addr sip;
311
312 if (*workgroup)
313 {
314 if (!find_master_ip(workgroup, &sip)) {
315 return 1;
316 }
317 fstrcpy(group, inet_ntoa(sip));
318 server_n = group;
319 } else
320 if (*srv->master)
321 {
322 if (srv->ifmastergroup)
323 {
324 if (!find_master_ip(srv->master, &sip)) {
325 return 11;
326 }
327 strncpy(srv->master, inet_ntoa(sip), sizeof(srv->master) - 1);
328 srv->ifmastergroup = 0;
329 }
330 server_n = srv->master;
331 } else
332 {
333 return 10;
334 }
335 }
336
337 make_nmb_name(&calling, global_myname(), 0x0);
338// make_nmb_name(&calling, "WORK", 0x0); // this machine name
339 make_nmb_name(&called , server_n, 0x20);
340
341 again:
342 zero_ip(&ip);
343
344 /* have to open a new connection */
345 if (!cli_initialise(c))
346 {
347 return 2;
348 }
349
350 if (!cli_connect(c, server_n, &ip))
351 {
352 return 3;
353 }
354 if (!cli_session_request(c, &calling, &called)) {
355 cli_shutdown(c);
356 if (strcmp(called.name, "*SMBSERVER")) {
357 make_nmb_name(&called , "*SMBSERVER", 0x20);
358 goto again;
359 }
360 return 4;
361 }
362
363 DEBUG(4,(" session request ok\n"));
364
365 if (!cli_negprot(c)) {
366 cli_shutdown(c);
367 return 5;
368 }
369
370 DEBUG(4,(" session setuping for <%s>/<%s> %d in <%s> %08x %08x %08x\n", srv->username, srv->password, strlen(srv->password), workgroup, c->protocol, c->sec_mode, c->capabilities));
371
372 rc = cli_session_setup(c, srv->username,
373 srv->password, strlen(srv->password),
374 srv->password, strlen(srv->password),
375 workgroup);
376 if (!rc)
377 {
378 DEBUG(4,("%s/%s login failed\n", srv->username, srv->password));
379 /* try an anonymous login if it failed */
380 rc = cli_session_setup(c, "", "", 1,"", 0, workgroup);
381 if (!rc)
382 {
383 DEBUG(4,("Anonymous login failed"));
384 cli_shutdown(c);
385 return 6;
386 }
387 }
388
389 DEBUG(4,(" session setup ok. Sending tconx <%s> <%s> %d\n", share, srv->password, strlen(srv->password)));
390
391 if (!cli_send_tconX(c, share, "?????",
392 srv->password, strlen(srv->password)+1)) {
393 cli_shutdown(c);
394 return 7;
395 }
396
397 DEBUG(4,(" tconx ok. cli caps %08x\n", c->capabilities));
398
399// srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
400
401 return 0;
402}
403
404/*****************************************************
405close a connection to a server
406*******************************************************/
407void _System smbwrp_disconnect(cli_state * cli)
408{
409 if (cli)
410 {
411 cli_shutdown(cli);
412 }
413}
414
415
416
417/*****************************************************
418a wrapper for open()
419*******************************************************/
420int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
421{
422 int fd = -1;
423
424 if (!cli || !file || !*file->fname)
425 {
426 return EINVAL;
427 }
428 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
429 {
430 file->denymode = DENY_NONE;
431 }
432
433 DEBUG(4,("cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode));
434 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
435 if (file->fd == -1)
436 {
437 return os2cli_errno(cli);
438 }
439 if (file->openmode & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))
440 {
441 time_t t;
442 file->mtime = time(NULL);
443 t = TimeDiff(file->mtime);
444 DEBUG(4,("cli_open mtime %lu %lu\n", file->mtime, t));
445 file->mtime -= t;
446 }
447 file->offset = 0;
448 return 0;
449}
450
451/*****************************************************
452a wrapper for read()
453*******************************************************/
454int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
455{
456 int ret;
457
458 if (!cli || !file || !buf || !result)
459 {
460 return EINVAL;
461 }
462
463 *result = 0;
464 ret = cli_read(cli, file->fd, buf, file->offset, count);
465 if (ret == -1)
466 {
467 return os2cli_errno(cli);
468 }
469
470 file->offset += ret;
471 *result = ret;
472 return 0;
473}
474
475
476
477/*****************************************************
478a wrapper for write()
479*******************************************************/
480int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
481{
482 int ret;
483
484 if (!cli || !file || !buf || !result)
485 {
486 return EINVAL;
487 }
488
489 *result = 0;
490//DEBUG(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
491 ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
492 if (ret == -1)
493 {
494 return os2cli_errno(cli);
495 }
496
497 file->offset += ret;
498 *result = ret;
499 return 0;
500}
501
502/*****************************************************
503a wrapper for close()
504*******************************************************/
505int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
506{
507 int rc = 0;
508 if (!cli || !file)
509 {
510 return EINVAL;
511 }
512
513
514 if (!cli_close(cli, file->fd))
515 {
516 return os2cli_errno(cli);
517 }
518 file->fd = -1;
519 file->offset = 0;
520 if (file->openattr || file->mtime)
521 {
522 DEBUG(4,("Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime + TimeDiff(file->mtime)));
523 if (!cli_setatr(cli, file->fname, file->openattr, file->mtime + TimeDiff(file->mtime)))
524 {
525 DEBUG(4,("Set attr on close failed %d\n", os2cli_errno(cli)));
526 //rc = os2cli_errno(cli);
527 }
528 file->openattr = 0;
529 file->mtime = 0;
530 }
531 *file->fname = 0;
532 return rc;
533}
534
535/*****************************************************
536a wrapper for setfilesize()
537*******************************************************/
538int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
539{
540 unsigned int data_len = 8;
541 unsigned int param_len = 6;
542 uint16 setup = TRANSACT2_SETFILEINFO;
543 pstring param;
544 char *rparam=NULL, *rdata=NULL;
545
546 memset(param, 0, param_len);
547 SSVAL(param,0,fnum);
548 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
549
550 if (!cli_send_trans(cli, SMBtrans2,
551 NULL, /* name */
552 -1, 0, /* fid, flags */
553 &setup, 1, 0, /* setup, length, max */
554 param, param_len, 2, /* param, length, max */
555 (char *)&newsize, sizeof(newsize), cli->max_xmit /* data, length, max */
556 )) {
557 return False;
558 }
559
560 if (!cli_receive_trans(cli, SMBtrans2,
561 &rparam, &param_len,
562 &rdata, &data_len)) {
563 return False;
564 }
565
566 SAFE_FREE(rdata);
567 SAFE_FREE(rparam);
568
569 return True;
570}
571
572int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
573{
574 int rc = 0;
575 if (!cli || !file)
576 {
577 return EINVAL;
578 }
579
580 DEBUG(4,("cli_setnewfileszie(%s) %lld\n", file->fname, newsize));
581 if (!cli_setfilenewsize(cli, file->fd, newsize))
582 {
583 if (newsize)
584 {
585 rc = os2cli_errno(cli);
586 }
587
588 if (!cli_close(cli, file->fd))
589 {
590 return os2cli_errno(cli);
591 }
592 file->fd = -1;
593 file->offset = 0;
594 file->openmode &= ~(O_CREAT | O_EXCL);
595 file->openmode |= O_TRUNC;
596 DEBUG(4,("cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode));
597 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
598 if (file->fd == -1)
599 {
600 return os2cli_errno(cli);
601 }
602 }
603 return 0;
604}
605
606/*****************************************************
607a wrapper for rename()
608*******************************************************/
609int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
610{
611 if (!cli || !oldname || !newname)
612 {
613 return EINVAL;
614 }
615
616 DEBUG(1,("Rename <%s> -> <%s>\n", oldname, newname));
617 //cli_unlink(cli, newname);
618// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
619 if (!cli_rename(cli, oldname, newname))
620 {
621 return os2cli_errno(cli);
622 }
623 return 0;
624}
625
626
627/*****************************************************
628a wrapper for chmod()
629*******************************************************/
630int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
631{
632 if (!cli || !finfo || !*finfo->fname)
633 {
634 return EINVAL;
635 }
636
637DEBUG(4,("Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + TimeDiff(finfo->mtime)));
638 if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : TimeDiff(finfo->mtime)))
639 && !cli_setatr(cli, finfo->fname, finfo->attr, 0))
640 {
641 return os2cli_errno(cli);
642 }
643 return 0;
644}
645
646/*****************************************************
647a wrapper for unlink()
648*******************************************************/
649int _System smbwrp_unlink(cli_state * cli, const char *fname)
650{
651 if (!cli || !fname)
652 {
653 return EINVAL;
654 }
655#if 0
656 if (strncmp(cli->dev, "LPT", 3) == 0)
657 {
658 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
659 if (job == -1)
660 {
661 goto failed;
662 }
663 if (cli_printjob_del(cli, job) != 0)
664 {
665 goto failed;
666 }
667 } else
668#endif
669 if (!cli_unlink(cli, fname))
670 {
671 return os2cli_errno(cli);
672 }
673 return 0;
674}
675
676/*****************************************************
677a wrapper for lseek()
678*******************************************************/
679int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
680{
681 off_t size;
682 if (!cli || !file)
683 {
684 return EINVAL;
685 }
686
687 DEBUG(4,("lseek %d %lld %lld\n", whence, offset, file->offset));
688
689 switch (whence) {
690 case SEEK_SET:
691 if (offset < 0)
692 {
693 return EINVAL;
694 }
695 file->offset = offset;
696 break;
697 case SEEK_CUR:
698 file->offset += offset;
699 break;
700 case SEEK_END:
701 if (offset > 0)
702 {
703 return EINVAL;
704 }
705 if (!cli_qfileinfo3(cli, file->fd,
706 NULL, &size, NULL, NULL, NULL,
707 NULL, NULL) &&
708 !cli_getattrE(cli, file->fd,
709 NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL))
710 {
711 return os2cli_errno(cli);
712 }
713 file->offset = size + offset;
714 break;
715 default: return EINVAL;
716 }
717
718 return 0;
719}
720
721/*****************************************************
722try to do a QPATHINFO and if that fails then do a getatr
723this is needed because win95 sometimes refuses the qpathinfo
724*******************************************************/
725int _System smbwrp_getattr(cli_state * cli, smbwrp_fileinfo *finfo)
726{
727 SMB_INO_T ino = 0;
728 if (!cli || !finfo || !*finfo->fname)
729 {
730 return EINVAL;
731 }
732 DEBUG(4,("getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname));
733 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
734 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
735 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
736 {
737 finfo->attr &= 0x7F;
738//DEBUG(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
739// finfo->ctime -= TimeDiff(finfo->ctime);
740// finfo->atime -= TimeDiff(finfo->atime);
741// finfo->mtime -= TimeDiff(finfo->mtime);
742 return 0;
743 }
744//DEBUG(2,("getattr rc1 %d\n", os2cli_errno(cli)));
745
746 /* if this is NT then don't bother with the getatr */
747 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
748 {
749 int rc = os2cli_errno(cli);
750 // cli_qpathinfo* reports EINVAL when path of given file not exists
751 // thus there is no real situation when EINVAL should be returned to
752 // client at this point, we just replace it to ENOTDIR
753 if (rc == EINVAL)
754 {
755 rc = ENOTDIR;
756 }
757 return rc;
758 }
759
760 if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, (size_t *)&finfo->size, (time_t *)&finfo->mtime))
761 {
762//DEBUG(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
763 finfo->mtime -= TimeDiff(finfo->mtime);
764 finfo->atime = finfo->mtime;
765 finfo->ctime = finfo->mtime;
766 cli->capabilities &= CAP_NOPATHINFO2;
767 return 0;
768 }
769 return os2cli_errno(cli);
770}
771
772/*****************************************************
773try to do a QPATHINFO and if that fails then do a getatr
774this is needed because win95 sometimes refuses the qpathinfo
775*******************************************************/
776int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
777{
778 SMB_INO_T ino = 0;
779 if (!cli || !file || !finfo)
780 {
781 return EINVAL;
782 }
783
784 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
785 if (!cli_qfileinfo3(cli, file->fd,
786 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
787 &ino))
788 {
789 if (!cli_getattrE(cli, file->fd,
790 (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime))
791 {
792 return os2cli_errno(cli);
793 }
794 else
795 {
796 finfo->ctime -= TimeDiff(finfo->ctime);
797 finfo->atime -= TimeDiff(finfo->atime);
798 finfo->mtime -= TimeDiff(finfo->mtime);
799 }
800 }
801 else
802 {
803// finfo->ctime -= TimeDiff(finfo->ctime);
804// finfo->atime -= TimeDiff(finfo->atime);
805// finfo->mtime -= TimeDiff(finfo->mtime);
806 }
807
808 return 0;
809}
810
811// =============================DIRECTORY ROUTINES============================
812
813/*****************************************************
814add a entry to a directory listing
815*******************************************************/
816static void smbwrp_dir_add(smbwrp_fileinfo *finfo, const char *mask, void *state)
817{
818 if (state && finfo)
819 {
820 filelist_state * st = (filelist_state *)state;
821 if (st->add_dir_entry)
822 {
823DEBUG(8,("adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen));
824 memcpy(&st->finfo, finfo, sizeof(st->finfo));
825 st->add_dir_entry(state);
826 }
827 }
828}
829
830static void smbwrp_dir_add_old(struct file_info *finfo, const char *mask, void *state)
831{
832 if (state && finfo)
833 {
834 filelist_state * st = (filelist_state *)state;
835 if (st->add_dir_entry)
836 {
837 strncpy(st->finfo.fname, finfo->name, sizeof(st->finfo.fname) - 1);
838 st->finfo.size = finfo->size;
839 st->finfo.easize = -1;
840 st->finfo.attr = finfo->mode;
841 st->finfo.ctime = finfo->ctime - TimeDiff(finfo->ctime);
842 st->finfo.mtime = finfo->mtime - TimeDiff(finfo->mtime);
843 st->finfo.atime = finfo->atime - TimeDiff(finfo->atime);
844 st->add_dir_entry(state);
845 }
846 }
847}
848
849static void smbwrp_special_add(char * name, void * state)
850{
851 smbwrp_fileinfo finfo = {0};
852
853 if (!name)
854 {
855 return;
856 }
857
858 ZERO_STRUCT(finfo);
859
860 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
861 finfo.attr = aRONLY | aDIR;
862
863 smbwrp_dir_add(&finfo, NULL, state);
864}
865
866static void smbwrp_printjob_add(struct print_job_info *job, void * state)
867{
868 smbwrp_fileinfo finfo = {0};
869
870 ZERO_STRUCT(finfo);
871
872//printf("Printjob <%s>\n", job->name);
873
874 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
875 finfo.mtime = job->t - TimeDiff(job->t);
876 finfo.atime = finfo.mtime;
877 finfo.ctime = finfo.mtime;
878 finfo.attr = aRONLY;
879 finfo.size = job->size;
880
881 smbwrp_dir_add(&finfo, NULL, state);
882}
883
884static void smbwrp_share_add(const char *share, uint32 type,
885 const char *comment, void *state)
886{
887 smbwrp_fileinfo finfo = {0};
888
889 if (strcmp(share,"IPC$") == 0) return;
890
891 ZERO_STRUCT(finfo);
892
893 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
894 finfo.attr = aRONLY | aDIR;
895
896 smbwrp_dir_add(&finfo, NULL, state);
897}
898
899
900/****************************************************************************
901 Interpret a long filename structure - this is mostly guesses at the moment.
902 The length of the structure is returned
903 The structure of a long filename depends on the info level. 260 is used
904 by NT and 2 is used by OS/2
905****************************************************************************/
906
907static int interpret_long_filename(struct cli_state *cli,
908 int level,char *p,smbwrp_fileinfo *finfo)
909{
910 extern file_info def_finfo;
911 int len;
912 char *base = p;
913 smbwrp_fileinfo finfo1;
914
915 if (!finfo) finfo = &finfo1;
916
917// memcpy(finfo,&def_finfo,sizeof(*finfo));
918 finfo->attr = def_finfo.mode;
919 finfo->mtime = def_finfo.mtime;
920 finfo->atime = def_finfo.atime;
921 finfo->ctime = def_finfo.ctime;
922 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
923
924 switch (level) {
925 case 1: /* OS/2 understands this */
926 /* these dates are converted to GMT by
927 make_unix_date */
928 finfo->ctime = make_unix_date2(p+4);
929 finfo->atime = make_unix_date2(p+8);
930 finfo->mtime = make_unix_date2(p+12);
931 finfo->size = IVAL(p,16);
932 finfo->attr = CVAL(p,24);
933 len = CVAL(p, 26);
934 p += 27;
935 p += clistr_align_in(cli, p, 0);
936 /* the len+2 below looks strange but it is
937 important to cope with the differences
938 between win2000 and win9x for this call
939 (tridge) */
940 p += clistr_pull(cli, finfo->fname, p,
941 sizeof(finfo->fname),
942 len+2,
943 STR_TERMINATE);
944 finfo->easize = -1;
945 return PTR_DIFF(p, base);
946
947 case 2: /* this is what OS/2 uses mostly */
948 /* these dates are converted to GMT by
949 make_unix_date */
950 finfo->ctime = make_unix_date2(p+4);
951 finfo->atime = make_unix_date2(p+8);
952 finfo->mtime = make_unix_date2(p+12);
953 finfo->size = IVAL(p,16);
954 finfo->attr = CVAL(p,24);
955 finfo->easize = IVAL(p,26);
956 len = CVAL(p, 30);
957 p += 31;
958 /* check for unisys! */
959 p += clistr_pull(cli, finfo->fname, p,
960 sizeof(finfo->fname),
961 len,
962 STR_NOALIGN);
963 return PTR_DIFF(p, base) + 1;
964
965 case 260: /* NT uses this, but also accepts 2 */
966 {
967 size_t namelen, slen;
968 p += 4; /* next entry offset */
969 p += 4; /* fileindex */
970
971 /* these dates appear to arrive in a
972 weird way. It seems to be localtime
973 plus the serverzone given in the
974 initial connect. This is GMT when
975 DST is not in effect and one hour
976 from GMT otherwise. Can this really
977 be right??
978
979 I suppose this could be called
980 kludge-GMT. Is is the GMT you get
981 by using the current DST setting on
982 a different localtime. It will be
983 cheap to calculate, I suppose, as
984 no DST tables will be needed */
985
986 finfo->ctime = interpret_long_date(p);
987 p += 8;
988 finfo->atime = interpret_long_date(p);
989 p += 8;
990 finfo->mtime = interpret_long_date(p);
991 p += 8;
992 p += 8;
993 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
994 p += 8;
995 p += 8; /* alloc size */
996 finfo->attr = CVAL(p,0);
997 p += 4;
998 namelen = IVAL(p,0);
999 p += 4;
1000 finfo->easize = IVAL(p,0);
1001 p += 4; /* EA size */
1002 slen = SVAL(p, 0);
1003 p += 2;
1004 p += 24; /* short name? */
1005 clistr_pull(cli, finfo->fname, p,
1006 sizeof(finfo->fname),
1007 namelen, 0);
1008 return SVAL(base, 0);
1009 }
1010 }
1011
1012 DEBUG(1,("Unknown long filename format %d\n",level));
1013 return(SVAL(p,0));
1014}
1015
1016/****************************************************************************
1017 Do a directory listing, calling fn on each file found.
1018 Modified from cli_list_new
1019****************************************************************************/
1020
1021static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1022 void (*fn)(smbwrp_fileinfo *, const char *, void *), void *state)
1023{
1024 int max_matches = 512;
1025 int info_level;
1026 char *p, *p2;
1027 pstring mask;
1028 smbwrp_fileinfo finfo;
1029 int i;
1030 char *tdl, *dirlist = NULL;
1031 int dirlist_len = 0;
1032 int total_received = -1;
1033 BOOL First = True;
1034 int ff_searchcount=0;
1035 int ff_eos=0;
1036 int ff_lastname=0;
1037 int ff_dir_handle=0;
1038 int loop_count = 0;
1039 char *rparam=NULL, *rdata=NULL;
1040 unsigned int param_len, data_len;
1041 uint16 setup;
1042 pstring param;
1043
1044 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1045 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1046
1047 DEBUG(4,("list_files level %d. mask <%s>\n", info_level, mask));
1048
1049 pstrcpy(mask,Mask);
1050
1051 while (ff_eos == 0) {
1052 loop_count++;
1053 if (loop_count > 200) {
1054 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
1055 break;
1056 }
1057
1058 if (First) {
1059 setup = TRANSACT2_FINDFIRST;
1060 SSVAL(param,0,attribute); /* attribute */
1061 SSVAL(param,2,max_matches); /* max count */
1062 SSVAL(param,4,4+2); /* resume required + close on end */
1063 SSVAL(param,6,info_level);
1064 SIVAL(param,8,0);
1065 p = param+12;
1066 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1067 STR_TERMINATE);
1068 } else {
1069 setup = TRANSACT2_FINDNEXT;
1070 SSVAL(param,0,ff_dir_handle);
1071 SSVAL(param,2,max_matches); /* max count */
1072 SSVAL(param,4,info_level);
1073 SIVAL(param,6,0); /* ff_resume_key */
1074 SSVAL(param,10,8+4+2); /* continue + resume required + close on end */
1075 p = param+12;
1076 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1077 STR_TERMINATE);
1078 }
1079
1080 param_len = PTR_DIFF(p, param);
1081 if (!cli_send_trans(cli, SMBtrans2,
1082 NULL, /* Name */
1083 -1, 0, /* fid, flags */
1084 &setup, 1, 0, /* setup, length, max */
1085 param, param_len, 10, /* param, length, max */
1086 NULL, 0,
1087#if 0
1088 /* w2k value. */
1089 MIN(16384,cli->max_xmit) /* data, length, max. */
1090#else
1091 cli->max_xmit /* data, length, max. */
1092#endif
1093 )) {
1094 break;
1095 }
1096
1097 if (!cli_receive_trans(cli, SMBtrans2,
1098 &rparam, &param_len,
1099 &rdata, &data_len) &&
1100 cli_is_dos_error(cli)) {
1101 /* we need to work around a Win95 bug - sometimes
1102 it gives ERRSRV/ERRerror temprarily */
1103 uint8 eclass;
1104 uint32 ecode;
1105 cli_dos_error(cli, &eclass, &ecode);
1106 if (eclass != ERRSRV || ecode != ERRerror)
1107 break;
1108 smb_msleep(100);
1109 continue;
1110 }
1111
1112
1113 if (cli_is_error(cli) || !rdata || !rparam)
1114 {
1115 if (First && info_level == 2)
1116 {
1117 // we have tried query ea size, but now will try without ea size
1118 info_level = 1;
1119 DEBUG(4,("list_files fallback to level %d\n", info_level));
1120 continue;
1121 }
1122 break;
1123 }
1124
1125 if (total_received == -1)
1126 total_received = 0;
1127
1128 /* parse out some important return info */
1129 p = rparam;
1130 if (First) {
1131 ff_dir_handle = SVAL(p,0);
1132 ff_searchcount = SVAL(p,2);
1133 ff_eos = SVAL(p,4);
1134 ff_lastname = SVAL(p,8);
1135 } else {
1136 ff_searchcount = SVAL(p,0);
1137 ff_eos = SVAL(p,2);
1138 ff_lastname = SVAL(p,6);
1139 }
1140 DEBUG(4,("list_files %d %d %d %d\n", ff_searchcount, ff_eos, ff_lastname, First));
1141
1142 if (ff_searchcount == 0)
1143 break;
1144
1145 /* point to the data bytes */
1146 p = rdata;
1147
1148 memset(&finfo, 0, sizeof(finfo));
1149 finfo.easize = -1;
1150 /* we might need the lastname for continuations */
1151 if (ff_lastname > 0) {
1152 switch(info_level) {
1153 case 260:
1154 clistr_pull(cli, mask, p+ff_lastname,
1155 sizeof(mask),
1156 data_len-ff_lastname,
1157 STR_TERMINATE);
1158 break;
1159 case 1:
1160 case 2:
1161 clistr_pull(cli, mask, p+ff_lastname+1,
1162 sizeof(mask),
1163 -1,
1164 STR_TERMINATE);
1165 break;
1166 }
1167 } else {
1168 pstrcpy(mask,"");
1169 }
1170
1171 /* and add them to the dirlist pool */
1172 tdl = Realloc(dirlist,dirlist_len + data_len);
1173
1174 if (!tdl) {
1175 DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
1176 break;
1177 } else {
1178 dirlist = tdl;
1179 }
1180
1181 /* put in a length for the last entry, to ensure we can chain entries
1182 into the next packet */
1183 for (p2=p,i=0;i<(ff_searchcount-1);i++)
1184 p2 += interpret_long_filename(cli,info_level,p2,NULL);
1185 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
1186
1187 /* grab the data for later use */
1188 memcpy(dirlist+dirlist_len,p,data_len);
1189 dirlist_len += data_len;
1190
1191 total_received += ff_searchcount;
1192
1193 SAFE_FREE(rdata);
1194 SAFE_FREE(rparam);
1195
1196 DEBUG(3,("received %d entries (eos=%d)\n",
1197 ff_searchcount,ff_eos));
1198
1199 if (ff_searchcount > 0)
1200 loop_count = 0;
1201
1202 First = False;
1203 }
1204
1205 DEBUG(3,("total received %d entries\n", total_received));
1206 for (p=dirlist,i=0;i<total_received;i++) {
1207 p += interpret_long_filename(cli,info_level,p,&finfo);
1208 fn(&finfo, Mask, state);
1209 }
1210
1211 /* free up the dirlist buffer */
1212 SAFE_FREE(dirlist);
1213 return(total_received);
1214}
1215
1216
1217/*****************************************************
1218open a directory on the server
1219*******************************************************/
1220int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1221{
1222 if (!srv || !cli || !state || !*state->mask)
1223 {
1224 return EINVAL;
1225 }
1226 DEBUG(1,("Filelist <%s> on master <%s> wgrp <%s> server <%s> share <%s> clidev <%s>\n", state->mask, srv->master, srv->workgroup, srv->server_name, srv->share_name, cli->dev));
1227 if (*srv->workgroup == 0 && *srv->server_name == 0)
1228 {
1229 smbwrp_special_add(".", state);
1230 smbwrp_special_add("..", state);
1231 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1232 smbwrp_share_add, state);
1233 } else
1234 if (*srv->server_name == 0)
1235 {
1236 smbwrp_special_add(".", state);
1237 smbwrp_special_add("..", state);
1238
1239 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1240 smbwrp_share_add, state);
1241 } else
1242 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1243 {
1244 smbwrp_special_add(".", state);
1245 smbwrp_special_add("..", state);
1246 if (cli_RNetShareEnum(cli, smbwrp_share_add, state) < 0)
1247 {
1248 return os2cli_errno(cli);
1249 }
1250 } else
1251 if (strncmp(cli->dev,"LPT",3) == 0)
1252 {
1253 smbwrp_special_add(".", state);
1254 smbwrp_special_add("..", state);
1255 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1256 {
1257 return os2cli_errno(cli);
1258 }
1259 }
1260 else
1261 {
1262#if 0
1263 if (strcmp(path,"\\") == 0) {
1264 smbwrp_special_add(".", state);
1265 smbwrp_special_add("..", state);
1266 }
1267#endif
1268#if 0
1269 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1270 smbwrp_dir_add_old, state) < 0)
1271#else
1272 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1273 smbwrp_dir_add, state) < 0)
1274#endif
1275 {
1276 return os2cli_errno(cli);
1277 }
1278 }
1279
1280 return 0;
1281}
1282
1283/*****************************************************
1284a wrapper for chdir()
1285*******************************************************/
1286int _System smbwrp_chdir(cli_state * cli, char *fname)
1287{
1288 unsigned short mode = aDIR;
1289 smbwrp_fileinfo finfo = {0};
1290 if (!cli || !fname)
1291 {
1292 return EINVAL;
1293 }
1294
1295 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1296 if (!smbwrp_getattr(cli, &finfo))
1297 {
1298 return os2cli_errno(cli);
1299 }
1300
1301 if (!(finfo.attr & aDIR)) {
1302 return ENOTDIR;
1303 }
1304
1305 return 0;
1306}
1307
1308
1309/*****************************************************
1310a wrapper for mkdir()
1311*******************************************************/
1312int _System smbwrp_mkdir(cli_state * cli, char *fname)
1313{
1314 if (!cli || !fname)
1315 {
1316 return EINVAL;
1317 }
1318
1319 if (!cli_mkdir(cli, fname))
1320 {
1321 return os2cli_errno(cli);
1322 }
1323 return 0;
1324}
1325
1326/*****************************************************
1327a wrapper for rmdir()
1328*******************************************************/
1329int _System smbwrp_rmdir(cli_state * cli, char *fname)
1330{
1331 if (!cli || !fname)
1332 {
1333 return EINVAL;
1334 }
1335
1336 if (!cli_rmdir(cli, fname))
1337 {
1338 return os2cli_errno(cli);
1339 }
1340 return 0;
1341}
1342
1343/*****************************************************
1344set EA for a path
1345*******************************************************/
1346int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1347{
1348 if (!cli || !fname || !name)
1349 {
1350 return EINVAL;
1351 }
1352 if (!cli_set_ea_path(cli, fname, name, value, size))
1353 {
1354 return os2cli_errno(cli);
1355 }
1356 return 0;
1357}
1358
1359/*****************************************************
1360set EA for a file
1361*******************************************************/
1362int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1363{
1364 if (!cli || !file || !name)
1365 {
1366 return EINVAL;
1367 }
1368 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1369 {
1370 return os2cli_errno(cli);
1371 }
1372 return 0;
1373}
1374
1375
1376#pragma pack(1)
1377typedef struct _FEA /* fea */
1378{
1379 unsigned char fEA; /* flags */
1380 unsigned char cbName; /* name length not including NULL */
1381 unsigned short cbValue; /* value length */
1382} FEA;
1383
1384typedef struct _FEALIST /* feal */
1385{
1386 unsigned long cbList; /* total bytes of structure including full list */
1387 FEA list[1]; /* variable length FEA structures */
1388} FEALIST;
1389#pragma pack()
1390
1391static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1392{
1393 int fnum, i;
1394 int gotsize = sizeof(unsigned long);
1395 size_t num_eas;
1396 struct ea_struct *ea_list = NULL;
1397 TALLOC_CTX *mem_ctx;
1398 FEA * p;
1399 FEALIST * pfealist;
1400 char * q;
1401
1402 mem_ctx = talloc_init("%d: ealist", _gettid());
1403 pfealist = (FEALIST *)buffer;
1404 pfealist->cbList = 0;
1405
1406 if (file)
1407 {
1408 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1409 {
1410 DEBUG(4,("ea_get_fnum list failed - %s\n", cli_errstr(cli)));
1411 talloc_destroy(mem_ctx);
1412 return os2cli_errno(cli);
1413 }
1414 }
1415 else
1416 {
1417 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1418 {
1419 DEBUG(4,("ea_get_file list failed - %s\n", cli_errstr(cli)));
1420 talloc_destroy(mem_ctx);
1421 return os2cli_errno(cli);
1422 }
1423 }
1424
1425 DEBUG(4,("num_eas = %d\n", num_eas));
1426
1427 // we will count that os/2 max EA size for file is 64kb
1428 p = pfealist->list;
1429 for (i = 0; i < num_eas; i++)
1430 {
1431 int namelen = strlen(ea_list[i].name);
1432 DEBUG(4, ("%d Got EA <%s> with namelen %d, size %d. Gross %d. Buf %d\n", i, ea_list[i].name, namelen, ea_list[i].value.length, gotsize, size));
1433 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1434 {
1435 DEBUG(4, ("Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length));
1436 continue;
1437 }
1438 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1439 if (size >= gotsize)
1440 {
1441 p->fEA = 0;
1442 p->cbName = namelen;
1443 p->cbValue = ea_list[i].value.length;
1444 q = (char *)(p + 1);
1445 strncpy(q, ea_list[i].name, namelen + 1);
1446 q += namelen + 1;
1447 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1448 p = (FEA *)(q + ea_list[i].value.length);
1449 }
1450 }
1451 pfealist->cbList = gotsize;
1452 DEBUG(4,("ret size = %d\n", gotsize));
1453
1454 talloc_destroy(mem_ctx);
1455 return 0;
1456}
1457
1458/*****************************************************
1459lists EA of a path
1460*******************************************************/
1461int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1462{
1463 if (!cli || !fname || !buffer)
1464 {
1465 return EINVAL;
1466 }
1467
1468 DEBUG(4,("EALIst for <%s>\n", fname));
1469 return unilistea(cli, fname, NULL, buffer, size);
1470}
1471
1472/*****************************************************
1473lists EA of a file
1474*******************************************************/
1475int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1476{
1477 if (!cli || !file || !buffer)
1478 {
1479 return EINVAL;
1480 }
1481
1482 DEBUG(4,("FEALIst for <%s>/%d\n", file->fname, file->fd));
1483 return unilistea(cli, NULL, file, buffer, size);
1484}
1485
1486/****************************************************************************
1487Check the space on a device.
1488****************************************************************************/
1489int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1490{
1491 int total, bsize, avail;
1492
1493 if (!cli || !pfsa)
1494 {
1495 return EINVAL;
1496 }
1497
1498 if (!cli_dskattr(cli, &bsize, &total, &avail))
1499 {
1500 DEBUG(4,("Error in dskattr: %s\n",cli_errstr(cli)));
1501 return os2cli_errno(cli);
1502 }
1503
1504 DEBUG(4,("\n\t\t%d blocks of size %d. %d blocks available\n",
1505 total, bsize, avail));
1506
1507 // YD currently Samba return it in MB!
1508 pfsa->cSectorUnit = 1;
1509 if (bsize > 65536)
1510 {
1511 pfsa->cUnit = total*1024;
1512 pfsa->cUnitAvail = avail*1024;
1513 pfsa->cbSector = bsize/1024;
1514 }
1515 else
1516 {
1517 pfsa->cUnit = total;
1518 pfsa->cUnitAvail = avail;
1519 pfsa->cbSector = bsize;
1520 }
1521
1522 return 0;
1523}
Note: See TracBrowser for help on using the repository browser.