18 ! |
18 ! |
19 |
19 |
20 !DirectoryStream primitiveDefinitions! |
20 !DirectoryStream primitiveDefinitions! |
21 %{ |
21 %{ |
22 |
22 |
23 #include <stdio.h> |
23 #define UNIX_LIKE |
24 #define _STDIO_H_INCLUDED_ |
24 #if defined(WIN32) |
25 |
25 # undef UNIX_LIKE |
26 #include <errno.h> |
26 #endif |
27 #define _ERRNO_H_INCLUDED_ |
27 |
28 |
28 #ifdef UNIX_LIKE |
29 #ifndef transputer |
29 |
30 # include <sys/types.h> |
30 # include <stdio.h> |
31 # include <sys/stat.h> |
31 # define _STDIO_H_INCLUDED_ |
32 |
32 |
33 # ifdef HAS_OPENDIR |
33 # include <errno.h> |
|
34 # define _ERRNO_H_INCLUDED_ |
|
35 |
|
36 # ifndef transputer |
34 # include <sys/types.h> |
37 # include <sys/types.h> |
35 # ifdef NEXT |
38 # include <sys/stat.h> |
36 # include <sys/dir.h> |
39 |
37 # else |
40 # ifdef HAS_OPENDIR |
38 # ifndef VMS |
41 # include <sys/types.h> |
39 # include <dirent.h> |
42 # ifdef NEXT |
40 # endif /* not VMS */ |
43 # include <sys/dir.h> |
|
44 # else |
|
45 # ifndef VMS |
|
46 # include <dirent.h> |
|
47 # endif /* not VMS */ |
|
48 # endif |
41 # endif |
49 # endif |
42 # endif |
50 # endif |
43 #endif |
|
44 |
51 |
45 /* |
52 /* |
46 * on some systems errno is a macro ... check for it here |
53 * on some systems errno is a macro ... check for it here |
47 */ |
54 */ |
48 #ifndef errno |
55 # ifndef errno |
49 extern errno; |
56 extern errno; |
50 #endif |
57 # endif |
|
58 #endif /* UNIX_LIKE */ |
|
59 |
|
60 #ifdef WIN32 |
|
61 |
|
62 # ifdef i386 |
|
63 # define _X86_ |
|
64 # endif |
|
65 |
|
66 # undef INT |
|
67 # undef Array |
|
68 # undef Number |
|
69 # undef Method |
|
70 # undef Point |
|
71 # undef Context |
|
72 # undef Rectangle |
|
73 |
|
74 # include <h/sys/types.h> /* */ |
|
75 # include <h/stdarg.h> /* */ |
|
76 # include <h/windef.h> /* */ |
|
77 # include <h/winbase.h> /* */ |
|
78 # include <h/wingdi.h> /* */ |
|
79 # include <h/winuser.h> /* */ |
|
80 |
|
81 # ifdef __DEF_Array |
|
82 # define Array __DEF_Array |
|
83 # endif |
|
84 # ifdef __DEF_Number |
|
85 # define Number __DEF_Number |
|
86 # endif |
|
87 # ifdef __DEF_Method |
|
88 # define Method __DEF_Method |
|
89 # endif |
|
90 # ifdef __DEF_Point |
|
91 # define Point __DEF_Point |
|
92 # endif |
|
93 # ifdef __DEF_Context |
|
94 # define Context __DEF_Context |
|
95 # endif |
|
96 |
|
97 # define __HANDLEVal(o) (HANDLE)__MKCP(o) |
|
98 |
|
99 #endif /* WIN32 */ |
51 |
100 |
52 %} |
101 %} |
53 ! ! |
102 ! ! |
54 |
103 |
55 !DirectoryStream primitiveFunctions! |
104 !DirectoryStream primitiveFunctions! |
351 Instances of DirectoryStream allow reading a file-directory, |
400 Instances of DirectoryStream allow reading a file-directory, |
352 as if it was a stream of filenames. |
401 as if it was a stream of filenames. |
353 Basically, its an interface to opendir, readdir and closedir. |
402 Basically, its an interface to opendir, readdir and closedir. |
354 |
403 |
355 [author:] |
404 [author:] |
356 Claus Gittinger |
405 Claus Gittinger |
357 " |
406 " |
358 ! ! |
407 ! ! |
359 |
408 |
360 !DirectoryStream class methodsFor:'instance creation'! |
409 !DirectoryStream class methodsFor:'instance creation'! |
361 |
410 |
376 |
425 |
377 |prevEntry nextEntry| |
426 |prevEntry nextEntry| |
378 %{ |
427 %{ |
379 #ifdef HAS_OPENDIR |
428 #ifdef HAS_OPENDIR |
380 DIR *d; |
429 DIR *d; |
381 #ifdef NEXT |
430 # ifdef NEXT |
382 struct direct *dp; |
431 struct direct *dp; |
383 #else |
432 # else |
384 struct dirent *dp; |
433 struct dirent *dp; |
385 #endif |
434 # endif |
386 OBJ dirP; |
435 OBJ dirP; |
387 |
436 |
388 |
|
389 if (__INST(hitEOF) != true && (dirP = __INST(dirPointer)) != nil) { |
437 if (__INST(hitEOF) != true && (dirP = __INST(dirPointer)) != nil) { |
390 __INST(lastErrorNumber) = nil; |
438 __INST(lastErrorNumber) = nil; |
391 d = (DIR *)__FILEVal(dirP); |
439 d = (DIR *)__FILEVal(dirP); |
392 |
440 |
393 __BEGIN_INTERRUPTABLE__ |
441 __BEGIN_INTERRUPTABLE__ |
394 do { |
442 do { |
395 errno = 0; |
443 errno = 0; |
396 dp = readdir(d); |
444 dp = readdir(d); |
397 } while ((dp == NULL) && (errno == EINTR)); |
445 } while ((dp == NULL) && (errno == EINTR)); |
398 __END_INTERRUPTABLE__ |
446 __END_INTERRUPTABLE__ |
399 |
447 |
400 if (dp != NULL) { |
448 if (dp != NULL) { |
401 nextEntry = __MKSTRING((char *)(dp->d_name) COMMA_CON); |
449 nextEntry = __MKSTRING((char *)(dp->d_name) COMMA_CON); |
402 } else { |
450 } else { |
403 if (errno) { |
451 if (errno) { |
404 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
452 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
405 } else { |
453 } else { |
406 __INST(hitEOF) = true; |
454 __INST(hitEOF) = true; |
407 } |
455 } |
408 } |
456 } |
409 } |
457 } |
410 #endif |
458 #else /* no HAS_OPENDIR */ |
|
459 # ifdef WIN32 |
|
460 HANDLE d; |
|
461 WIN32_FIND_DATA data; |
|
462 OBJ dirP; |
|
463 |
|
464 if (__INST(hitEOF) != true && (dirP = __INST(dirPointer)) != nil) { |
|
465 __INST(lastErrorNumber) = nil; |
|
466 d = __HANDLEVal(dirP); |
|
467 |
|
468 if (FindNextFile(d, &data)) { |
|
469 nextEntry = __MKSTRING( data.cFileName ); |
|
470 } else { |
|
471 __INST(hitEOF) = true; |
|
472 } |
|
473 } |
|
474 # endif /* WIN32 */ |
|
475 #endif /* HAS_OPENDIR */ |
411 %}. |
476 %}. |
412 lastErrorNumber notNil ifTrue:[^ self ioError]. |
477 lastErrorNumber notNil ifTrue:[^ self ioError]. |
413 prevEntry := readAhead. |
478 prevEntry := readAhead. |
414 readAhead := nextEntry. |
479 readAhead := nextEntry. |
415 prevEntry isNil ifTrue:[^ self pastEnd]. |
480 prevEntry isNil ifTrue:[^ self pastEnd]. |
438 |
503 |
439 if ((dp = __INST(dirPointer)) != nil) { |
504 if ((dp = __INST(dirPointer)) != nil) { |
440 __INST(dirPointer) = nil; |
505 __INST(dirPointer) = nil; |
441 closedir( (DIR *)(__FILEVal(dp)) ); |
506 closedir( (DIR *)(__FILEVal(dp)) ); |
442 } |
507 } |
|
508 #else |
|
509 # ifdef WIN32 |
|
510 OBJ dp; |
|
511 |
|
512 if ((dp = __INST(dirPointer)) != nil) { |
|
513 __INST(dirPointer) = nil; |
|
514 FindClose( __HANDLEVal(dp) ); |
|
515 } |
|
516 # endif |
443 #endif |
517 #endif |
444 %} |
518 %} |
445 ! ! |
519 ! ! |
446 |
520 |
447 !DirectoryStream methodsFor:'private'! |
521 !DirectoryStream methodsFor:'private'! |
448 |
522 |
449 openForReading |
523 openForReading |
450 "open the file for readonly" |
524 "open the file for readonly" |
451 |
525 |
452 |ok| |
526 |ok entry| |
453 |
527 |
454 mode := #readonly. |
528 mode := #readonly. |
455 %{ |
529 %{ |
456 #ifdef HAS_OPENDIR |
530 #ifdef HAS_OPENDIR |
457 DIR *d; |
531 DIR *d; |
474 __INST(dirPointer) = dp = __MKOBJ(d); __STORE(self, dp); |
548 __INST(dirPointer) = dp = __MKOBJ(d); __STORE(self, dp); |
475 ok = true; |
549 ok = true; |
476 } |
550 } |
477 } |
551 } |
478 } |
552 } |
|
553 #else |
|
554 # ifdef WIN32 |
|
555 HANDLE d; |
|
556 OBJ path, dp; |
|
557 char pattern[512]; |
|
558 WIN32_FIND_DATA data; |
|
559 |
|
560 ok = false; |
|
561 if (__INST(dirPointer) == nil) { |
|
562 path = __INST(pathName); |
|
563 if (__isString(path)) { |
|
564 strcpy(pattern, __stringVal(path)); |
|
565 strcat(pattern, "\\*"); |
|
566 d = FindFirstFile(pattern, &data); |
|
567 if (d == INVALID_HANDLE_VALUE) { |
|
568 __INST(lastErrorNumber) = __MKSMALLINT(GetLastError()); |
|
569 } else { |
|
570 __INST(dirPointer) = dp = __MKOBJ(d); __STORE(self, dp); |
|
571 entry = __MKSTRING( data.cFileName ); |
|
572 ok = true; |
|
573 } |
|
574 } |
|
575 } |
|
576 # endif |
479 #endif |
577 #endif |
480 %}. |
578 %}. |
481 ok isNil ifTrue:[ |
579 ok isNil ifTrue:[ |
482 " |
580 " |
483 opendir not avalable - use slower pipe |
581 opendir not avalable - use slower pipe |
485 ^ PipeStream readingFrom:('cd ' , pathName , '; ls -a') |
583 ^ PipeStream readingFrom:('cd ' , pathName , '; ls -a') |
486 ]. |
584 ]. |
487 |
585 |
488 (ok == true) ifTrue:[ |
586 (ok == true) ifTrue:[ |
489 Lobby register:self. |
587 Lobby register:self. |
490 self nextLine. "read 1st entry into readAhead buffer" |
588 entry isNil ifTrue:[ |
|
589 self nextLine. "read 1st entry into readAhead buffer" |
|
590 ] ifFalse:[ |
|
591 readAhead := entry. |
|
592 ]. |
491 ^ self |
593 ^ self |
492 ]. |
594 ]. |
493 dirPointer notNil ifTrue:[^ self errorOpen]. |
595 dirPointer notNil ifTrue:[^ self errorOpen]. |
494 lastErrorNumber notNil ifTrue:[^ self openError]. |
596 lastErrorNumber notNil ifTrue:[^ self openError]. |
495 ^ nil |
597 ^ nil |