source: trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.c@ 6

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

Client code changes for 3.0.25 upgrade.

  • Property svn:eol-style set to native
File size: 25.5 KB
Line 
1#define INCL_DOSERRORS
2#define INCL_DOS
3#include <os2emx.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <string.h>
8#include <sys/types.h>
9#include <process.h>
10#include <sys/time.h>
11#include "smbwrp.h"
12#include "smbcd.h"
13
14#define SMBCD_MAX_THREADS 100
15
16int debuglevel = 0;
17HMTX logmutex = 0;
18char *logfile = NULL;
19
20char *timestring(int hires);
21
22#if 0
23int debug_parse_levels(const char *params_str)
24{
25 return 1;
26}
27
28void dbgflush( void )
29{
30// if (!logfile) fflush(stdout);
31}
32#endif
33
34int debuglvl(int level)
35{
36 return (level <= debuglevel) ? 1 : 0;
37}
38
39int debugheader(int level, char * file, char * func, int line)
40{
41 int rc;
42 if (level > debuglevel)
43 {
44 return 0;
45 }
46 rc = DosRequestMutexSem(logmutex, -1L);
47 if (rc)
48 {
49 return 0;
50 }
51 rc = 1;
52 do
53 {
54 FILE * f;
55 struct timeval tv;
56 time_t t;
57 char buf[80] = {0};
58 if (logfile)
59 {
60 f = fopen(logfile, "a");
61 if (!f)
62 {
63 rc = 0;
64 break;
65 }
66 }
67 else
68 {
69 f = stdout;
70 }
71 gettimeofday(&tv, NULL);
72 t = time(NULL);
73// strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
74 strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
75 fprintf(f, "%s.%d: %d %d: %s:%s(%d) :", buf, tv.tv_usec / 10000, level, (long)_gettid(), file, func, line);
76 if (logfile)
77 {
78 fclose(f);
79 }
80 }
81 while (0);
82 DosReleaseMutexSem(logmutex);
83 return rc;
84}
85
86int debugmessage(char * fmt, ...)
87{
88 int rc;
89 rc = DosRequestMutexSem(logmutex, -1L);
90 if (rc)
91 {
92 return 0;
93 }
94 do
95 {
96 FILE * f;
97 va_list args;
98 if (logfile)
99 {
100 f = fopen(logfile, "a");
101 if (!f)
102 {
103 break;
104 }
105 }
106 else
107 {
108 f = stdout;
109 }
110 va_start(args, fmt);
111 vfprintf(f, fmt, args);
112 va_end(args);
113 if (logfile)
114 {
115 fclose(f);
116 }
117 }
118 while (0);
119 DosReleaseMutexSem(logmutex);
120 return 0;
121}
122
123void debuglocal(int level, const char * fmt, ...)
124{
125 int rc;
126 if (level > debuglevel)
127 {
128 return;
129 }
130 rc = DosRequestMutexSem(logmutex, -1L);
131 if (rc)
132 {
133 return;
134 }
135 do
136 {
137 FILE * f;
138 struct timeval tv;
139 char buf[80] = {0};
140 va_list args;
141 if (logfile)
142 {
143 f = fopen(logfile, "a");
144 if (!f)
145 {
146 break;
147 }
148 }
149 else
150 {
151 f = stdout;
152 }
153 gettimeofday(&tv, NULL);
154 strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
155 fprintf(f, "%s.%d: %d %d: ", buf, tv.tv_usec / 10000, level, (long)_gettid());
156 va_start(args, fmt);
157 vfprintf(f, fmt, args);
158 va_end(args);
159 if (logfile)
160 {
161 fclose(f);
162 }
163 }
164 while (0);
165 DosReleaseMutexSem(logmutex);
166}
167
168// map errno errors to API errors
169int maperror(int rc)
170{
171 switch (rc)
172 {
173 case 0 : return NO_ERROR ; /* NO_ERROR */
174 case 1 : return ERROR_ACCESS_DENIED ; /* EPERM - Operation not permitted */
175 case 2 : return ERROR_FILE_NOT_FOUND ; /* ENOENT - No such file or directory */
176 case 3 : return ERROR_PID_MISMATCH ; /* ESRCH - No such process */
177 case 4 : return ERROR_INTERRUPT ; /* EINTR - Interrupted system call */
178 case 5 : return ERROR_READ_FAULT ; /* EIO - I/O error */
179 case 6 : return ERROR_BAD_UNIT ; /* ENXIO - No such device or address */
180 case 7 : return ERROR_INVALID_DATA ; /* E2BIG - Arguments or environment too big */
181 case 8 : return ERROR_BAD_EXE_FORMAT ; /* ENOEXEC - Invalid executable file format */
182 case 9 : return ERROR_INVALID_HANDLE ; /* EBADF - Bad file number */
183 case 10 : return ERROR_NO_CHILD_PROCESS ; /* ECHILD - No child processes */
184 case 11 : return ERROR_BUSY ; /* EAGAIN - Resource temporarily unavailable */
185 case 12 : return ERROR_NOT_ENOUGH_MEMORY ; /* ENOMEM - Not enough memory */
186 case 13 : return ERROR_ACCESS_DENIED ; /* EACCES - Permission denied */
187 case 14 : return ERROR_INVALID_ADDRESS ; /* EFAULT - Bad address */
188 case 15 : return ERROR_NOT_LOCKED ; /* ENOLCK - No locks available */
189 case 16 : return ERROR_BUSY ; /* EBUSY - Resource busy */
190 case 17 : return ERROR_FILE_EXISTS ; /* EEXIST - File exists */
191 case 18 : return ERROR_NOT_SAME_DEVICE ; /* EXDEV - Cross-device link */
192 case 19 : return ERROR_REM_NOT_LIST ; /* ENODEV - No such device */
193 case 20 : return ERROR_PATH_NOT_FOUND ; /* ENOTDIR - Not a directory */
194 case 21 : return ERROR_DIRECTORY ; /* EISDIR - Is a directory */
195 case 22 : return ERROR_INVALID_PARAMETER ; /* EINVAL - Invalid argument */
196 case 23 : return ERROR_TOO_MANY_OPEN_FILES ; /* ENFILE - Too many open files in system */
197 case 24 : return ERROR_TOO_MANY_OPENS ; /* EMFILE - Too many open files */
198 case 25 : return ERROR_MOD_NOT_FOUND ; /* ENOTTY - Inappropriate ioctl */
199 case 26 : return ERROR_LOCK_VIOLATION ; /* EDEADLK - Resource deadlock avoided */
200 case 27 : return ERROR_TRANSFER_TOO_LONG ; /* EFBIG - File too large */
201 case 28 : return ERROR_DISK_FULL ; /* ENOSPC - Disk full */
202 case 29 : return ERROR_SEEK ; /* ESPIPE - Invalid seek */
203 case 30 : return ERROR_WRITE_PROTECT ; /* EROFS - Read-only file system */
204 case 31 : return ERROR_TOO_MANY_OPEN_FILES ; /* EMLINK - Too many links */
205 case 32 : return ERROR_BROKEN_PIPE ; /* EPIPE - Broken pipe */
206 case 33 : return ERROR_INVALID_LEVEL ; /* EDOM - Domain error */
207 case 34 : return ERROR_FILENAME_EXCED_RANGE ; /* ERANGE - Result too large */
208 case 35 : return ERROR_DIR_NOT_EMPTY ; /* ENOTEMPTY - Directory not empty */
209 case 36 : return ERROR_BUSY_DRIVE ; /* EINPROGRESS - Operation now in progress */
210 case 37 : return ERROR_INVALID_FUNCTION ; /* ENOSYS - Function not implemented */
211 case 38 : return ERROR_FILENAME_EXCED_RANGE ; /* ENAMETOOLONG - File name too long */
212 case 39 : return ERROR_KBD_FOCUS_REQUIRED ; /* EDESTADDRREQ - Destination address required */
213 case 40 : return ERROR_TRANSFER_TOO_LONG ; /* EMSGSIZE - Message too long */
214 case 48 : return ERROR_NETWORK_BUSY ; /* EADDRINUSE - Address already in use */
215 case 49 : return ERROR_INFO_NOT_AVAIL ; /* EADDRNOTAVAIL - Can't assigned requested address */
216 case 50 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETDOWN - Network is down */
217 case 51 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETUNREACH - Network is unreachable */
218 case 52 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETRESET - Network dropped connection on reset */
219 case 53 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNABORTED - Software caused connection abort */
220 case 54 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNRESET - Connection reset by peer */
221 case 55 : return ERROR_BUFFER_OVERFLOW ; /* ENOBUFS - No buffer space available */
222 case 56 : return ERROR_PIPE_BUSY ; /* EISCONN - Socket is already connected */
223 case 57 : return ERROR_PIPE_NOT_CONNECTED ; /* ENOTCONN - Socket is not connected */
224 case 58 : return ERROR_ALREADY_SHUTDOWN ; /* ESHUTDOWN - Can't send after socket shutdown */
225 case 60 : return ERROR_TIMEOUT ; /* ETIMEDOUT - Connection timed out */
226 case 61 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNREFUSED - Connection refused */
227 case 63 : return ERROR_INVALID_BLOCK ; /* ENOTSOCK - Socket operation on non-socket */
228 case 64 : return ERROR_BAD_FORMAT ; /* EHOSTDOWN - Host is down */
229 case 65 : return ERROR_BAD_NETPATH ; /* EHOSTUNREACH - No route to host */
230 case 66 : return ERROR_BUSY_DRIVE ; /* EALREADY - Operation already in progress */
231 }
232 return rc + 40000;
233}
234
235char * getlastslash(char * path)
236{
237 char * p;
238 if (!path)
239 {
240 return NULL;
241 }
242 for (p = path + strlen(path) - 1; p >= path; p--)
243 {
244 if (*p == '\\' || *p == '/')
245 {
246 return p;
247 }
248 }
249 return NULL;
250}
251
252void _System add_dir_entry(void * st)
253{
254 int rc;
255 filelist_state * state = (filelist_state *)st;
256 if (!state || !*(state->finfo.fname))
257 {
258 return;
259 }
260 if (!state->data)
261 {
262 debuglocal(0,"Malformed filelist_state!\n");
263 return;
264 }
265 if (state->bufferlen < state->datalen + sizeof(state->finfo))
266 {
267 // send this portion of buffer to client
268 smb_request req = {0};
269 smb_response resp = {0};
270 unsigned long action;
271 resp.length = state->datalen;
272 resp.rc = ERROR_MORE_DATA;
273 rc = DosWrite(state->pipe, &resp, sizeof(resp), &action);
274 if (rc || action < sizeof(resp))
275 {
276 debuglocal(1,"Failed to write to pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
277 }
278 else
279 {
280 rc = DosRead(state->pipe, &req, sizeof(req), &action);
281 if (rc || action < sizeof(req))
282 {
283 debuglocal(0,"Failed to read from pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
284 return;
285 }
286 }
287 state->datalen = 0;
288 }
289 memcpy(state->data + state->datalen, &state->finfo, sizeof(state->finfo));
290 state->datalen += sizeof(state->finfo);
291}
292
293// rc = 0 - continue, rc = 1 - quit with response
294int processrequest(HPIPE pipe, cli_state * cli, unsigned long * reconnect, smbwrp_server * srv, smb_request *req, smb_response *res)
295{
296 int rc = 0;
297 int callrc = 0;
298 char * data;
299 if (!pipe || !cli || !reconnect || !srv || !req || !req->param || req->paramlen > req->length || !res)
300 {
301 debuglocal(0,"invalid structures\n");
302 return ERROR_INVALID_PARAMETER;
303 }
304 data = req->param + req->paramlen;
305// memset(res, 0, sizeof(*res));
306 debuglocal(1,"Client request %d paramlen %d len %d, reconnect %d. State %08x\n", req->request, req->paramlen, req->length, *reconnect, cli);
307 if (*reconnect == 2)
308 {
309 debuglocal(1,"Reconnecting to last server requested\n");
310 res->rc = smbwrp_connect(srv, cli);
311 if (res->rc)
312 {
313 debuglocal(1,"Client reconnect resprc %d\n", res->rc);
314 return NO_ERROR;
315 }
316 *reconnect = 1;
317 }
318 switch (req->request)
319 {
320 case SMBREQ_INIT :
321 {
322 res->value = sizeof(smbwrp_server) << 16 | getpid();
323 } break;
324 case SMBREQ_INITCOMPLETE :
325 {
326 callrc = DosGetSharedMem(req->param, PAG_READ | PAG_WRITE);
327 if (callrc)
328 {
329 debuglocal(0,"Cant get sharedmem of %x : %d\n", req->param, callrc);
330 res->rc = callrc;
331 rc = 1;
332 break;
333 }
334 } break;
335 case SMBREQ_CONNECT :
336 {
337 if (req->paramlen < sizeof(smbwrp_server))
338 {
339 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server));
340 res->rc = ERROR_INVALID_PARAMETER;
341 break;
342 }
343 res->rc = smbwrp_connect((smbwrp_server *)req->param, cli);
344 if (!res->rc)
345 {
346 memcpy(srv, req->param, sizeof(smbwrp_server));
347 *reconnect = 1;
348 }
349 } break;
350 case SMBREQ_DISCONNECT :
351 {
352 smbwrp_disconnect(cli);
353 } break;
354 case SMBREQ_OPEN :
355 {
356 if (req->paramlen < sizeof(smbwrp_file))
357 {
358 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
359 res->rc = ERROR_INVALID_PARAMETER;
360 break;
361 }
362 callrc = smbwrp_open(cli, (smbwrp_file *)req->param);
363 res->rc = maperror(callrc);
364 } break;
365 case SMBREQ_CLOSE :
366 {
367 if (req->paramlen < sizeof(smbwrp_file))
368 {
369 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
370 res->rc = ERROR_INVALID_PARAMETER;
371 break;
372 }
373 callrc = smbwrp_close(cli, (smbwrp_file *)req->param);
374 res->rc = maperror(callrc);
375 } break;
376 case SMBREQ_READ :
377 {
378 if (req->paramlen < sizeof(smbwrp_file))
379 {
380 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
381 res->rc = ERROR_INVALID_PARAMETER;
382 break;
383 }
384 callrc = smbwrp_read(cli, (smbwrp_file *)req->param,
385 data, req->length - req->paramlen, (unsigned long *)&res->value);
386 res->rc = maperror(callrc);
387 } break;
388 case SMBREQ_WRITE :
389 {
390 if (req->paramlen < sizeof(smbwrp_file))
391 {
392 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
393 res->rc = ERROR_INVALID_PARAMETER;
394 break;
395 }
396 callrc = smbwrp_write(cli, (smbwrp_file *)req->param,
397 data, req->length - req->paramlen, (unsigned long *)&res->value);
398 res->rc = maperror(callrc);
399 } break;
400 case SMBREQ_LSEEK :
401 {
402 if (req->paramlen < sizeof(smbwrp_file) + sizeof(int) + sizeof(long long))
403 {
404 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(int) + sizeof(long long));
405 res->rc = ERROR_INVALID_PARAMETER;
406 break;
407 }
408 callrc = smbwrp_lseek(cli,
409 (smbwrp_file *)req->param,
410 *(int *)(req->param + sizeof(smbwrp_file)),
411 *(long long *)(req->param + sizeof(smbwrp_file) + sizeof(int)));
412 res->rc = maperror(callrc);
413 } break;
414 case SMBREQ_SETINFO :
415 {
416 if (req->paramlen < sizeof(smbwrp_fileinfo))
417 {
418 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_fileinfo));
419 res->rc = ERROR_INVALID_PARAMETER;
420 break;
421 }
422 callrc = smbwrp_setattr(cli, (smbwrp_fileinfo *)req->param);
423 res->rc = maperror(callrc);
424 } break;
425 case SMBREQ_GETINFO :
426 {
427 if (req->length < sizeof(smbwrp_fileinfo))
428 {
429 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_fileinfo));
430 res->rc = ERROR_INVALID_PARAMETER;
431 break;
432 }
433 callrc = smbwrp_getattr(cli, (smbwrp_fileinfo *)req->param);
434 res->rc = maperror(callrc);
435 } break;
436 case SMBREQ_FGETINFO :
437 {
438 if (req->length < sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo))
439 {
440 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo));
441 res->rc = ERROR_INVALID_PARAMETER;
442 break;
443 }
444 callrc = smbwrp_fgetattr(cli,
445 (smbwrp_file *)req->param,
446 (smbwrp_fileinfo *)(req->param + sizeof(smbwrp_file)));
447 res->rc = maperror(callrc);
448 } break;
449 case SMBREQ_FILELIST :
450 {
451 filelist_state state;
452 char * p;
453 if (req->paramlen < sizeof(smbwrp_server) + (CCHMAXPATH + 1))
454 {
455 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server) + (CCHMAXPATH + 1));
456 res->rc = ERROR_INVALID_PARAMETER;
457 break;
458 }
459 state.pipe = pipe;
460 state.bufferlen = req->length - req->paramlen;
461 if (state.bufferlen < sizeof(state))
462 {
463 debuglocal(0,"Not enough buffer to hold data %d\n", state.bufferlen);
464 res->rc = ERROR_BUFFER_OVERFLOW;
465 break;
466 }
467 strncpy(state.mask, req->param + sizeof(smbwrp_server), sizeof(state.mask) - 2);
468 p = getlastslash(state.mask);
469 if (p)
470 {
471 *(p + 1) = '*';
472 *(p + 2) = 0;
473 }
474 else
475 {
476 strcpy(state.mask, "\\*");
477 }
478 state.data = data;
479 state.datalen = 0;
480 state.add_dir_entry = add_dir_entry;
481 callrc = smbwrp_filelist((smbwrp_server *)req->param, cli, &state);
482 res->rc = maperror(callrc);
483 res->length = state.datalen;
484 } break;
485 case SMBREQ_RENAME :
486 {
487 if (req->paramlen < 2 * (CCHMAXPATH + 1))
488 {
489 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, 2 * (CCHMAXPATH + 1));
490 res->rc = ERROR_INVALID_PARAMETER;
491 break;
492 }
493 callrc = smbwrp_rename(cli, req->param,
494 req->param + (CCHMAXPATH + 1));
495 res->rc = maperror(callrc);
496 } break;
497 case SMBREQ_UNLINK :
498 {
499 if (req->paramlen < CCHMAXPATH + 1)
500 {
501 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
502 res->rc = ERROR_INVALID_PARAMETER;
503 break;
504 }
505 callrc = smbwrp_unlink(cli, req->param);
506 res->rc = maperror(callrc);
507 } break;
508 case SMBREQ_MKDIR :
509 {
510 if (req->paramlen < CCHMAXPATH + 1)
511 {
512 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
513 res->rc = ERROR_INVALID_PARAMETER;
514 break;
515 }
516 callrc = smbwrp_mkdir(cli, req->param);
517 res->rc = maperror(callrc);
518 } break;
519 case SMBREQ_RMDIR :
520 {
521 if (req->paramlen < CCHMAXPATH + 1)
522 {
523 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
524 res->rc = ERROR_INVALID_PARAMETER;
525 break;
526 }
527 callrc = smbwrp_rmdir(cli, req->param);
528 res->rc = maperror(callrc);
529 } break;
530 case SMBREQ_CHDIR :
531 {
532 if (req->paramlen < CCHMAXPATH + 1)
533 {
534 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
535 res->rc = ERROR_INVALID_PARAMETER;
536 break;
537 }
538 callrc = smbwrp_chdir(cli, req->param);
539 res->rc = maperror(callrc);
540 } break;
541 case SMBREQ_NEWSIZE :
542 {
543 if (req->paramlen < sizeof(smbwrp_file) + sizeof(off_t))
544 {
545 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(off_t));
546 res->rc = ERROR_INVALID_PARAMETER;
547 break;
548 }
549 callrc = smbwrp_setfilesize(cli,
550 (smbwrp_file *)req->param,
551 *(off_t *)(req->param + sizeof(smbwrp_file)));
552 res->rc = maperror(callrc);
553 } break;
554 case SMBREQ_SETEA :
555 {
556 // got FEA there
557 FEALIST * pfealist;
558 FEA * pfea;
559 unsigned long done = sizeof(long);
560 if (req->paramlen < CCHMAXPATH + 1 + sizeof(FEALIST))
561 {
562 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + sizeof(FEALIST));
563 res->rc = ERROR_INVALID_PARAMETER;
564 break;
565 }
566 pfealist = (FEALIST *)(req->param + CCHMAXPATH + 1);
567 if (req->paramlen < CCHMAXPATH + 1 + pfealist->cbList)
568 {
569 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + pfealist->cbList);
570 res->rc = ERROR_INVALID_PARAMETER;
571 break;
572 }
573 pfea = pfealist->list;
574 while (done < pfealist->cbList)
575 {
576 callrc = smbwrp_setea(cli, req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
577 if (callrc)
578 {
579 break;
580 }
581 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
582 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
583 }
584 res->rc = maperror(callrc);
585 } break;
586 case SMBREQ_FSETEA :
587 {
588 // got FEA there
589 FEALIST * pfealist;
590 FEA * pfea;
591 unsigned long done = sizeof(long);
592 if (req->paramlen < sizeof(smbwrp_file) + sizeof(FEALIST))
593 {
594 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(FEALIST));
595 res->rc = ERROR_INVALID_PARAMETER;
596 break;
597 }
598 pfealist = (FEALIST *)(req->param + sizeof(smbwrp_file));
599 if (req->paramlen < sizeof(smbwrp_file) + pfealist->cbList)
600 {
601 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + pfealist->cbList);
602 res->rc = ERROR_INVALID_PARAMETER;
603 break;
604 }
605 pfea = pfealist->list;
606 while (done < pfealist->cbList)
607 {
608 callrc = smbwrp_fsetea(cli, (smbwrp_file *)req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
609 if (callrc)
610 {
611 break;
612 }
613 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
614 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
615 }
616 res->rc = maperror(callrc);
617 } break;
618 case SMBREQ_LISTEA :
619 {
620 FEALIST * pfealist;
621 if (req->paramlen < CCHMAXPATH + 1)
622 {
623 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
624 res->rc = ERROR_INVALID_PARAMETER;
625 break;
626 }
627 pfealist = (FEALIST *)data;
628 callrc = smbwrp_listea(cli, req->param, data, req->length);
629 res->rc = maperror(callrc);
630 if (!res->rc && pfealist->cbList > req->length)
631 {
632 res->rc = ERROR_BUFFER_OVERFLOW;
633 }
634 } break;
635 case SMBREQ_FLISTEA :
636 {
637 FEALIST * pfealist;
638 if (req->paramlen < sizeof(smbwrp_file))
639 {
640 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
641 res->rc = ERROR_INVALID_PARAMETER;
642 break;
643 }
644 pfealist = (FEALIST *)data;
645 callrc = smbwrp_flistea(cli, (smbwrp_file *)req->param, data, req->length);
646 res->rc = maperror(callrc);
647 if (!res->rc && pfealist->cbList > req->length)
648 {
649 res->rc = ERROR_BUFFER_OVERFLOW;
650 }
651 } break;
652 case SMBREQ_DSKATTR :
653 {
654 if (req->paramlen < sizeof(FSALLOCATE))
655 {
656 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(FSALLOCATE));
657 res->rc = ERROR_INVALID_PARAMETER;
658 break;
659 }
660 callrc = smbwrp_dskattr(cli, (FSALLOCATE*)req->param);
661 res->rc = maperror(callrc);
662 res->length = callrc ? 0 : req->length;
663 } break;
664 default :
665 {
666 debuglocal(0,"Unknown request %d\n", req->request);
667 // rc = ERROR_INVALID_FUNCTION; ??
668 res->rc = ERROR_INVALID_FUNCTION;
669 }
670 }
671 debuglocal(1,"Client request %d rc %d resprc %d resplength %d\n", req->request, rc, res->rc, res->length);
672 if (res->rc == ERROR_PIPE_NOT_CONNECTED && *reconnect == 1)
673 {
674 debuglocal(1,"Setting reconnect flag\n");
675 *reconnect = 2;
676 }
677 return rc;
678}
679
680void clientthread(void * arg)
681{
682 HPIPE pipe;
683 int rc;
684 smbwrp_server srv = {0};
685 smb_request req = {0};
686 smb_response resp = {0};
687 unsigned long reconnect = 0;
688 unsigned long action;
689 cli_state * cli;
690
691 if (!arg)
692 {
693 debuglocal(0,"Passed null pipe pointer\n");
694 return;
695 }
696 pipe = (HPIPE)arg;
697 rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
698 if (rc)
699 {
700 rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE);
701 }
702 cli = (cli_state *)calloc(smbwrp_getclisize(), 1);
703 if (rc || !cli)
704 {
705 debuglocal(0,"Not enough memory to initialize client structure\n");
706 DosClose(pipe);
707 return;
708 }
709 memset(cli, 0, smbwrp_getclisize());
710 debuglocal(0,"opening client pipe %d\n", pipe);
711 for (;;)
712 {
713 rc = DosRead(pipe, &req, sizeof(req), &action);
714 if (rc || action < sizeof(req))
715 {
716 debuglocal(0,"Failed to read from pipe %d: %d %d\n", pipe, rc, action);
717 break;
718 }
719 // rc = 0 - continue, rc = 1 - quit with response
720 memset(&resp, 0, sizeof(resp));
721 rc = processrequest(pipe, cli, &reconnect, &srv, &req, &resp);
722 if (rc < 2)
723 {
724 rc = DosWrite(pipe, &resp, sizeof(resp), &action);
725 if (rc || action < sizeof(resp))
726 {
727 debuglocal(0,"Failed to write to pipe %d: %d %d\n", pipe, rc, action);
728 }
729 }
730 if (rc)
731 {
732 debuglocal(0,"shutdown client %d with rc %d\n", pipe, rc);
733 break;
734 }
735 }
736 debuglocal(0,"closing client pipe %d\n", pipe);
737 DosDisConnectNPipe(pipe);
738 DosClose(pipe);
739 memset(cli, 0, smbwrp_getclisize());
740 DosFreeMem(cli);
741}
742
743void help(void)
744{
745 printf("Usage: smbcd [-d/--debug <debuglevel>] [-q/--quiet] [-l/--logfile <logfile>]\n");
746}
747
748int main(int argc, char ** argv)
749{
750 int rc = 0, quiet = 0;
751 HPIPE pipe, newpipe;
752 unsigned long action;
753
754#ifdef __OS2__
755 rc = DosSetPriority(
756 0, /* Scope: only one process */
757 4, /* set to PRTYC_FOREGROUNDSERVER */
758 31, /* set delta - was 0 */
759 0); /* Assume current process */
760 printf( "Daemon priority set to PRTYC_FOREGROUNDSERVER\n");
761#endif
762
763 for (argc--, argv++; argc > 0; argc--, argv++)
764 {
765 if (strcmp(argv[0], "-d") == 0 || strcmp(argv[0], "--debug") == 0)
766 {
767 if (argc < 2)
768 {
769 rc = 1;
770 printf("Parameter missing after <%s>", argv[0]);
771 break;
772 }
773 debuglevel = atoi(argv[1]);
774 if (debuglevel <= 0 || debuglevel > 10)
775 {
776 rc = 1;
777 printf("Wrong value <%s> for parameter <%s>", argv[1], argv[0]);
778 break;
779 }
780 if (debuglevel == 10)
781 {
782 // smbcd crashed on dump_msg used to dump messages on level 10
783 debuglevel--;
784 }
785 argc --;
786 argv ++;
787 } else
788 if (strcmp(argv[0], "-l") == 0 || strcmp(argv[0], "--logfile") == 0)
789 {
790 FILE * test;
791 if (argc < 2)
792 {
793 rc = 1;
794 printf("Parameter missing after <%s>", argv[0]);
795 break;
796 }
797 logfile = argv[1];
798 test = fopen(argv[1], "a");
799 if (test == NULL)
800 {
801 rc = 1;
802 printf("Cant open log file <%s>\n", logfile);
803 break;
804 }
805 fclose(test);
806 argc --;
807 argv ++;
808 } else
809 if (strcmp(argv[0], "-q") == 0 || strcmp(argv[0], "--quiet") == 0)
810 {
811 quiet = 1;
812 } else
813 {
814 printf("Unknown parameter <%s>\n", argv[0]);
815 rc = 1;
816 break;
817 }
818 }
819 if (rc)
820 {
821 help();
822 return 1;
823 }
824 if (quiet)
825 {
826 debuglevel = -10;
827 }
828 rc = DosCreateMutexSem(NULL, &logmutex, 0, 0);
829 if (rc)
830 {
831 if (!quiet) printf("DosCreateMutexSem %d\n", rc);
832 return 1;
833 }
834 rc = smbwrp_init();
835 if (rc)
836 {
837 debuglocal(0,"Init failed with rc %d\n", rc);
838 return 1;
839 }
840 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
841 if (rc == NO_ERROR)
842 {
843 debuglocal(0,"Pipe %s already exists. May be duplicate smbcd is running\n", PIPENAME);
844 DosClose(pipe);
845 return 1;
846 }
847
848 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
849 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
850 600, 600, 1000);
851 if (rc)
852 {
853 debuglocal(0,"Cant create named pipe %d\n", rc);
854 return 1;
855 }
856
857 debuglocal(1,"Entering main loop. My pid is %d. My mutex is %08x. My debuglevel is %d. Client state size %d\n", getpid(), logmutex, debuglevel, smbwrp_getclisize());
858
859 for (;;)
860 {
861 do
862 {
863 rc = DosConnectNPipe(pipe);
864 } while (rc == ERROR_INTERRUPT);
865
866 if (!rc)
867 {
868 debuglocal(1,"New client connected %d to pipe %d\n", rc, pipe);
869 int tid = _beginthread(clientthread, NULL, 655360, (void *)pipe);
870 if (tid < 0)
871 {
872 debuglocal(0,"Failed to create client thread\n");
873 rc = 0xFFFF;
874 }
875 }
876
877 if (rc)
878 {
879 debuglocal(0,"Client failed to connect %d\n", rc);
880 DosDisConnectNPipe(pipe);
881 DosClose(pipe);
882 }
883
884 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
885 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
886 600, 600, 1000);
887 if (rc)
888 {
889 debuglocal(0,"Cant create new named pipe %d\n", rc);
890 break;
891 }
892 }
893
894 DosDisConnectNPipe(pipe);
895 DosClose(pipe);
896 DosCloseMutexSem(logmutex);
897 return 0;
898}
Note: See TracBrowser for help on using the repository browser.