source: trunk-3.0/source/ndpsmb/smbcd.c@ 101

Last change on this file since 101 was 75, checked in by Paul Smedley, 18 years ago

return generated path info for workgroups and servers instead of an error code.

  • Property svn:eol-style set to native
File size: 25.3 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 250
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 cli_state * cli = *_cli;
300
301 if (!pipe || !_cli || !reconnect || !srv || !req || !req->param || req->paramlen > req->length || !res)
302 {
303 debuglocal(0,"invalid structures\n");
304 return ERROR_INVALID_PARAMETER;
305 }
306 data = req->param + req->paramlen;
307// memset(res, 0, sizeof(*res));
308 debuglocal(1,"Client request %d paramlen %d len %d, reconnect %d. State %08x\n", req->request, req->paramlen, req->length, *reconnect, cli);
309 if (*reconnect == 2)
310 {
311 debuglocal(1,"Reconnecting to last server requested\n");
312 res->rc = smbwrp_connect(srv, _cli);
313 if (res->rc)
314 {
315 debuglocal(1,"Client reconnect resprc %d\n", res->rc);
316 return ERROR_ACCESS_DENIED;
317 }
318 *reconnect = 1;
319 }
320 switch (req->request)
321 {
322 case SMBREQ_INIT :
323 {
324 res->value = sizeof(smbwrp_server) << 16 | getpid();
325 } break;
326 case SMBREQ_INITCOMPLETE :
327 {
328 callrc = DosGetSharedMem(req->param, PAG_READ | PAG_WRITE);
329 if (callrc)
330 {
331 debuglocal(0,"Cant get sharedmem of %x : %d\n", req->param, callrc);
332 res->rc = callrc;
333 rc = 1;
334 break;
335 }
336 } break;
337 case SMBREQ_CONNECT :
338 {
339 if (req->paramlen < sizeof(smbwrp_server))
340 {
341 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server));
342 res->rc = ERROR_INVALID_PARAMETER;
343 break;
344 }
345 res->rc = smbwrp_connect((smbwrp_server *)req->param, _cli);
346 if (!res->rc)
347 {
348 memcpy(srv, req->param, sizeof(smbwrp_server));
349 *reconnect = 1;
350 }
351 else
352 {
353 res->rc = ERROR_ACCESS_DENIED;
354 }
355 } break;
356 case SMBREQ_DISCONNECT :
357 {
358 smbwrp_disconnect(_cli);
359 } break;
360 case SMBREQ_OPEN :
361 {
362 if (req->paramlen < sizeof(smbwrp_file))
363 {
364 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
365 res->rc = ERROR_INVALID_PARAMETER;
366 break;
367 }
368 callrc = smbwrp_open(cli, (smbwrp_file *)req->param);
369 res->rc = maperror(callrc);
370 } break;
371 case SMBREQ_CLOSE :
372 {
373 if (req->paramlen < sizeof(smbwrp_file))
374 {
375 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
376 res->rc = ERROR_INVALID_PARAMETER;
377 break;
378 }
379 callrc = smbwrp_close(cli, (smbwrp_file *)req->param);
380 res->rc = maperror(callrc);
381 } break;
382 case SMBREQ_READ :
383 {
384 if (req->paramlen < sizeof(smbwrp_file))
385 {
386 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
387 res->rc = ERROR_INVALID_PARAMETER;
388 break;
389 }
390 callrc = smbwrp_read(cli, (smbwrp_file *)req->param,
391 data, req->length - req->paramlen, (unsigned long *)&res->value);
392 res->rc = maperror(callrc);
393 } break;
394 case SMBREQ_WRITE :
395 {
396 if (req->paramlen < sizeof(smbwrp_file))
397 {
398 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
399 res->rc = ERROR_INVALID_PARAMETER;
400 break;
401 }
402 callrc = smbwrp_write(cli, (smbwrp_file *)req->param,
403 data, req->length - req->paramlen, (unsigned long *)&res->value);
404 res->rc = maperror(callrc);
405 } break;
406 case SMBREQ_LSEEK :
407 {
408 if (req->paramlen < sizeof(smbwrp_file) + sizeof(int) + sizeof(long long))
409 {
410 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(int) + sizeof(long long));
411 res->rc = ERROR_INVALID_PARAMETER;
412 break;
413 }
414 callrc = smbwrp_lseek(cli,
415 (smbwrp_file *)req->param,
416 *(int *)(req->param + sizeof(smbwrp_file)),
417 *(long long *)(req->param + sizeof(smbwrp_file) + sizeof(int)));
418 res->rc = maperror(callrc);
419 } break;
420 case SMBREQ_SETINFO :
421 {
422 if (req->paramlen < sizeof(smbwrp_fileinfo))
423 {
424 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_fileinfo));
425 res->rc = ERROR_INVALID_PARAMETER;
426 break;
427 }
428 callrc = smbwrp_setattr(cli, (smbwrp_fileinfo *)req->param);
429 res->rc = maperror(callrc);
430 } break;
431 case SMBREQ_GETINFO :
432 {
433 if (req->length < sizeof(smbwrp_fileinfo))
434 {
435 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_fileinfo));
436 res->rc = ERROR_INVALID_PARAMETER;
437 break;
438 }
439 callrc = smbwrp_getattr(srv, cli, (smbwrp_fileinfo *)req->param);
440 res->rc = maperror(callrc);
441 } break;
442 case SMBREQ_FGETINFO :
443 {
444 if (req->length < sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo))
445 {
446 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo));
447 res->rc = ERROR_INVALID_PARAMETER;
448 break;
449 }
450 callrc = smbwrp_fgetattr(cli,
451 (smbwrp_file *)req->param,
452 (smbwrp_fileinfo *)(req->param + sizeof(smbwrp_file)));
453 res->rc = maperror(callrc);
454 } break;
455 case SMBREQ_FILELIST :
456 {
457 filelist_state state;
458 char * p;
459 if (req->paramlen < sizeof(smbwrp_server) + (CCHMAXPATH + 1))
460 {
461 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server) + (CCHMAXPATH + 1));
462 res->rc = ERROR_INVALID_PARAMETER;
463 break;
464 }
465 state.pipe = pipe;
466 state.bufferlen = req->length - req->paramlen;
467 if (state.bufferlen < sizeof(state))
468 {
469 debuglocal(0,"Not enough buffer to hold data %d\n", state.bufferlen);
470 res->rc = ERROR_BUFFER_OVERFLOW;
471 break;
472 }
473 strncpy(state.mask, req->param + sizeof(smbwrp_server), sizeof(state.mask) - 2);
474 p = getlastslash(state.mask);
475 if (p)
476 {
477 *(p + 1) = '*';
478 *(p + 2) = 0;
479 }
480 else
481 {
482 strcpy(state.mask, "\\*");
483 }
484 state.data = data;
485 state.datalen = 0;
486 state.add_dir_entry = add_dir_entry;
487 callrc = smbwrp_filelist((smbwrp_server *)req->param, cli, &state);
488 res->rc = maperror(callrc);
489 res->length = state.datalen;
490 } break;
491 case SMBREQ_RENAME :
492 {
493 if (req->paramlen < 2 * (CCHMAXPATH + 1))
494 {
495 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, 2 * (CCHMAXPATH + 1));
496 res->rc = ERROR_INVALID_PARAMETER;
497 break;
498 }
499 callrc = smbwrp_rename(cli, req->param,
500 req->param + (CCHMAXPATH + 1));
501 res->rc = maperror(callrc);
502 } break;
503 case SMBREQ_UNLINK :
504 {
505 if (req->paramlen < CCHMAXPATH + 1)
506 {
507 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
508 res->rc = ERROR_INVALID_PARAMETER;
509 break;
510 }
511 callrc = smbwrp_unlink(cli, req->param);
512 res->rc = maperror(callrc);
513 } break;
514 case SMBREQ_MKDIR :
515 {
516 if (req->paramlen < CCHMAXPATH + 1)
517 {
518 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
519 res->rc = ERROR_INVALID_PARAMETER;
520 break;
521 }
522 callrc = smbwrp_mkdir(cli, req->param);
523 res->rc = maperror(callrc);
524 } break;
525 case SMBREQ_RMDIR :
526 {
527 if (req->paramlen < CCHMAXPATH + 1)
528 {
529 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
530 res->rc = ERROR_INVALID_PARAMETER;
531 break;
532 }
533 callrc = smbwrp_rmdir(cli, req->param);
534 res->rc = maperror(callrc);
535 } break;
536 case SMBREQ_CHDIR :
537 {
538 if (req->paramlen < CCHMAXPATH + 1)
539 {
540 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
541 res->rc = ERROR_INVALID_PARAMETER;
542 break;
543 }
544 callrc = smbwrp_chdir(srv, cli, req->param);
545 res->rc = maperror(callrc);
546 } break;
547 case SMBREQ_NEWSIZE :
548 {
549 if (req->paramlen < sizeof(smbwrp_file) + sizeof(off_t))
550 {
551 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(off_t));
552 res->rc = ERROR_INVALID_PARAMETER;
553 break;
554 }
555 callrc = smbwrp_setfilesize(cli,
556 (smbwrp_file *)req->param,
557 *(off_t *)(req->param + sizeof(smbwrp_file)));
558 res->rc = maperror(callrc);
559 } break;
560 case SMBREQ_SETEA :
561 {
562 // got FEA there
563 FEALIST * pfealist;
564 FEA * pfea;
565 unsigned long done = sizeof(long);
566 if (req->paramlen < CCHMAXPATH + 1 + sizeof(FEALIST))
567 {
568 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + sizeof(FEALIST));
569 res->rc = ERROR_INVALID_PARAMETER;
570 break;
571 }
572 pfealist = (FEALIST *)(req->param + CCHMAXPATH + 1);
573 if (req->paramlen < CCHMAXPATH + 1 + pfealist->cbList)
574 {
575 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + pfealist->cbList);
576 res->rc = ERROR_INVALID_PARAMETER;
577 break;
578 }
579 pfea = pfealist->list;
580 while (done < pfealist->cbList)
581 {
582 callrc = smbwrp_setea(cli, req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
583 if (callrc)
584 {
585 break;
586 }
587 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
588 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
589 }
590 res->rc = maperror(callrc);
591 } break;
592 case SMBREQ_FSETEA :
593 {
594 // got FEA there
595 FEALIST * pfealist;
596 FEA * pfea;
597 unsigned long done = sizeof(long);
598 if (req->paramlen < sizeof(smbwrp_file) + sizeof(FEALIST))
599 {
600 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(FEALIST));
601 res->rc = ERROR_INVALID_PARAMETER;
602 break;
603 }
604 pfealist = (FEALIST *)(req->param + sizeof(smbwrp_file));
605 if (req->paramlen < sizeof(smbwrp_file) + pfealist->cbList)
606 {
607 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + pfealist->cbList);
608 res->rc = ERROR_INVALID_PARAMETER;
609 break;
610 }
611 pfea = pfealist->list;
612 while (done < pfealist->cbList)
613 {
614 callrc = smbwrp_fsetea(cli, (smbwrp_file *)req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
615 if (callrc)
616 {
617 break;
618 }
619 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
620 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
621 }
622 res->rc = maperror(callrc);
623 } break;
624 case SMBREQ_LISTEA :
625 {
626 FEALIST * pfealist;
627 if (req->paramlen < CCHMAXPATH + 1)
628 {
629 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
630 res->rc = ERROR_INVALID_PARAMETER;
631 break;
632 }
633 pfealist = (FEALIST *)data;
634 callrc = smbwrp_listea(cli, req->param, data, req->length);
635 res->rc = maperror(callrc);
636 if (!res->rc && pfealist->cbList > req->length)
637 {
638 res->rc = ERROR_BUFFER_OVERFLOW;
639 }
640 } break;
641 case SMBREQ_FLISTEA :
642 {
643 FEALIST * pfealist;
644 if (req->paramlen < sizeof(smbwrp_file))
645 {
646 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
647 res->rc = ERROR_INVALID_PARAMETER;
648 break;
649 }
650 pfealist = (FEALIST *)data;
651 callrc = smbwrp_flistea(cli, (smbwrp_file *)req->param, data, req->length);
652 res->rc = maperror(callrc);
653 if (!res->rc && pfealist->cbList > req->length)
654 {
655 res->rc = ERROR_BUFFER_OVERFLOW;
656 }
657 } break;
658 case SMBREQ_DSKATTR :
659 {
660 if (req->paramlen < sizeof(FSALLOCATE))
661 {
662 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(FSALLOCATE));
663 res->rc = ERROR_INVALID_PARAMETER;
664 break;
665 }
666 callrc = smbwrp_dskattr(cli, (FSALLOCATE*)req->param);
667 res->rc = maperror(callrc);
668 res->length = callrc ? 0 : req->length;
669 } break;
670 default :
671 {
672 debuglocal(0,"Unknown request %d\n", req->request);
673 // rc = ERROR_INVALID_FUNCTION; ??
674 res->rc = ERROR_INVALID_FUNCTION;
675 }
676 }
677 debuglocal(1,"Client request %d rc %d resprc %d resplength %d\n", req->request, rc, res->rc, res->length);
678 if (res->rc == ERROR_PIPE_NOT_CONNECTED && *reconnect == 1)
679 {
680 debuglocal(1,"Setting reconnect flag\n");
681 *reconnect = 2;
682 }
683 return rc;
684}
685
686void clientthread(void * arg)
687{
688 HPIPE pipe;
689 int rc;
690 smbwrp_server srv = {0};
691 smb_request req = {0};
692 smb_response resp = {0};
693 unsigned long reconnect = 0;
694 unsigned long action;
695 cli_state * cli = 0;
696
697 if (!arg)
698 {
699 debuglocal(0,"Passed null pipe pointer\n");
700 return;
701 }
702 pipe = (HPIPE)arg;
703
704 debuglocal(0,"opening client pipe %d\n", pipe);
705 for (;;)
706 {
707 rc = DosRead(pipe, &req, sizeof(req), &action);
708 if (rc || action < sizeof(req))
709 {
710 debuglocal(0,"Failed to read from pipe %d: %d %d\n", pipe, rc, action);
711 break;
712 }
713 // rc = 0 - continue, rc = 1 - quit with response
714 memset(&resp, 0, sizeof(resp));
715 rc = processrequest(pipe, &cli, &reconnect, &srv, &req, &resp);
716 if (rc < 2)
717 {
718 rc = DosWrite(pipe, &resp, sizeof(resp), &action);
719 if (rc || action < sizeof(resp))
720 {
721 debuglocal(0,"Failed to write to pipe %d: %d %d\n", pipe, rc, action);
722 }
723 }
724 if (rc)
725 {
726 debuglocal(0,"shutdown client %d with rc %d\n", pipe, rc);
727 break;
728 }
729 // YD this seems to make PMView to show thumbnails faster,
730 // no delay shown while using FOC.
731 DosSleep(0);
732 }
733 debuglocal(0,"closing client pipe %d\n", pipe);
734 DosDisConnectNPipe(pipe);
735 DosClose(pipe);
736 free (cli);
737}
738
739void help(void)
740{
741 printf("Usage: smbcd [-d/--debug <debuglevel>] [-q/--quiet] [-l/--logfile <logfile>]\n");
742}
743
744int main(int argc, char ** argv)
745{
746 int rc = 0, quiet = 0;
747 HPIPE pipe, newpipe;
748 unsigned long action;
749
750#ifdef __OS2__
751 rc = DosSetPriority(
752 0, /* Scope: only one process */
753 4, /* set to PRTYC_FOREGROUNDSERVER */
754 0, /* set delta - was 0 */
755 0); /* Assume current process */
756 printf( "Daemon priority set to PRTYC_FOREGROUNDSERVER\n");
757#endif
758
759 for (argc--, argv++; argc > 0; argc--, argv++)
760 {
761 if (strcmp(argv[0], "-d") == 0 || strcmp(argv[0], "--debug") == 0)
762 {
763 if (argc < 2)
764 {
765 rc = 1;
766 printf("Parameter missing after <%s>", argv[0]);
767 break;
768 }
769 debuglevel = atoi(argv[1]);
770 if (debuglevel <= 0 || debuglevel > 10)
771 {
772 rc = 1;
773 printf("Wrong value <%s> for parameter <%s>", argv[1], argv[0]);
774 break;
775 }
776 if (debuglevel == 10)
777 {
778 // smbcd crashed on dump_msg used to dump messages on level 10
779 debuglevel--;
780 }
781 argc --;
782 argv ++;
783 } else
784 if (strcmp(argv[0], "-l") == 0 || strcmp(argv[0], "--logfile") == 0)
785 {
786 FILE * test;
787 if (argc < 2)
788 {
789 rc = 1;
790 printf("Parameter missing after <%s>", argv[0]);
791 break;
792 }
793 logfile = argv[1];
794 test = fopen(argv[1], "a");
795 if (test == NULL)
796 {
797 rc = 1;
798 printf("Cant open log file <%s>\n", logfile);
799 break;
800 }
801 fclose(test);
802 argc --;
803 argv ++;
804 } else
805 if (strcmp(argv[0], "-q") == 0 || strcmp(argv[0], "--quiet") == 0)
806 {
807 quiet = 1;
808 } else
809 {
810 printf("Unknown parameter <%s>\n", argv[0]);
811 rc = 1;
812 break;
813 }
814 }
815 if (rc)
816 {
817 help();
818 return 1;
819 }
820 if (quiet)
821 {
822 debuglevel = -10;
823 }
824 rc = DosCreateMutexSem(NULL, &logmutex, 0, 0);
825 if (rc)
826 {
827 if (!quiet) printf("DosCreateMutexSem %d\n", rc);
828 return 1;
829 }
830 rc = smbwrp_init();
831 if (rc)
832 {
833 debuglocal(0,"Init failed with rc %d\n", rc);
834 return 1;
835 }
836 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
837 if (rc == NO_ERROR)
838 {
839 debuglocal(0,"Pipe %s already exists. May be duplicate smbcd is running\n", PIPENAME);
840 DosClose(pipe);
841 return 1;
842 }
843
844 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
845 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
846 600, 600, 1000);
847 if (rc)
848 {
849 debuglocal(0,"Cant create named pipe %d\n", rc);
850 return 1;
851 }
852
853 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());
854
855 for (;;)
856 {
857 do
858 {
859 rc = DosConnectNPipe(pipe);
860 } while (rc == ERROR_INTERRUPT);
861
862 if (!rc)
863 {
864 debuglocal(1,"New client connected %d to pipe %d\n", rc, pipe);
865 int tid = _beginthread(clientthread, NULL, 655360, (void *)pipe);
866 if (tid < 0)
867 {
868 debuglocal(0,"Failed to create client thread\n");
869 rc = 0xFFFF;
870 }
871 }
872
873 if (rc)
874 {
875 debuglocal(0,"Client failed to connect %d\n", rc);
876 DosDisConnectNPipe(pipe);
877 DosClose(pipe);
878 }
879
880 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
881 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
882 600, 600, 1000);
883 if (rc)
884 {
885 debuglocal(0,"Cant create new named pipe %d\n", rc);
886 break;
887 }
888 }
889
890 DosDisConnectNPipe(pipe);
891 DosClose(pipe);
892 DosCloseMutexSem(logmutex);
893 return 0;
894}
Note: See TracBrowser for help on using the repository browser.