6 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
12 #include "dos_intern.h"
13 #include <proto/exec.h>
14 #include <exec/memory.h>
15 #include <exec/types.h>
18 /*****************************************************************************
21 #include <dos/dosasl.h>
22 #include <proto/dos.h>
24 AROS_LH2(LONG
, MatchFirst
,
27 AROS_LHA(STRPTR
, pat
, D1
),
28 AROS_LHA(struct AnchorPath
*, AP
, D2
),
31 struct DosLibrary
*, DOSBase
, 137, Dos
)
35 Searches for the first file or directory that matches a given pattern.
36 MatchFirst() initializes the AnchorPath structure for you but you
37 must initilize the following fields: ap_Flags, ap_Strlen, ap_BreakBits
38 and ap_FoundBreak. The first call to MatchFirst() also passes you
39 the first matching file which you can examine in ap_Info and the directory
40 the files is in in ap_Current->an_Lock. After the first call to
41 MatchFirst() call MatchNext().
42 The search begins whereever the current directory is set to. See
44 For more info on patterns see ParsePattern().
47 pat - pattern to search for
48 AP - pointer to (initilized) AnchorPath structure
52 other = DOS error code
59 Copying of the relative path to ap_Buf is not implemented yet
62 MatchNext(), MatchEnd(), ParsePattern(), Examine(), CurrentDir()
67 *****************************************************************************/
72 struct AChain
* AC_Prev
= NULL
;
83 AP
->ap_Current
= NULL
;
85 PatLength
= 2*strlen(pat
)+2;
86 ParsedPattern
= AllocMem(PatLength
, MEMF_ANY
);
89 if (NULL
!= ParsedPattern
)
98 bug("matchfirst: ParsedPattern mem okay. Calling ParsePatternNoCase\n");
101 ** Put the preparsed string to some memory
102 ** If there are any wildcards then leave info
104 if (1 == ParsePatternNoCase(pat
, ParsedPattern
, PatLength
))
105 AP
->ap_Flags
|= (BYTE
)APF_ITSWILD
;
107 //bug("matchfirst: ParsePatternNoCase returned: pattern = \"%s\"\n", ParsedPattern);
110 ** First I search for the very first ':'. If a '/' comes along
111 ** before that I quit. The string before and including the ':'
112 ** is assumed to be an assigned directory, for example 'libs:'.
113 ** So I will start looking for the pattern in that directory.
117 if (ParsedPattern
[PatEnd
] == ':')
124 if ( ParsedPattern
[PatEnd
] == '/' ||
125 ParsedPattern
[PatEnd
] == '\0' ||
126 (ParsedPattern
[PatEnd
] & 0x80) != 0
127 /* a token or nonprintable letter */)
137 ** Only if success == TRUE an assigned dir was found.
142 ** try to create a lock to that assigned dir.
144 char Remember
= ParsedPattern
[PatEnd
+1];
146 ParsedPattern
[PatEnd
] = '\0';
147 firstlock
= Lock(ParsedPattern
, ACCESS_READ
);
148 origdir
= CurrentDir(firstlock
);
151 ** check whether an error occurred
153 if (NULL
== firstlock
)
155 FreeMem(ParsedPattern
, PatLength
);
156 return IoErr(); // ERROR_DIR_NOT_FOUND; /* !!! hope that's the right error code... */
160 ** I have the correct lock.
162 ParsedPattern
[PatEnd
] = Remember
;
165 } /* if (TRUE == success) */
169 ** Create a lock to the current dir.
171 origdir
= CurrentDir(NULL
);
172 firstlock
= DupLock(origdir
);
175 FreeMem(ParsedPattern
, PatLength
);
179 (void)CurrentDir(firstlock
);
182 bug("MatchFirst: origdir = %x\n", origdir
);
183 bug("MatchFirst: firstlock = %x\n", firstlock
);
186 ** Allocate an AChain structure for the original directory.
188 AC
= (struct AChain
*)AllocVec(sizeof(struct AChain
), MEMF_CLEAR
);
194 FreeMem(ParsedPattern
, PatLength
);
198 return ERROR_NO_FREE_STORE
;
201 AC
->an_Lock
= origdir
;
202 AC
->an_Flags
= DDF_Completed
|DDF_Single
;
209 ** Build the Anchor Chain. For every subdirectory I allocate
210 ** an AChain structure and link them all together
212 while (FALSE
== AllDone
)
215 ** Search for the next '/' in the pattern and everything behind
216 ** the previous '/' and before this '/' will go to an_String
220 if (ParsedPattern
[PatEnd
] == '\0')
226 if (ParsedPattern
[PatEnd
] == '/')
235 AC
= AllocVec(sizeof(struct AChain
)+(PatEnd
-PatStart
+2), MEMF_CLEAR
);
238 /* not so bad if this was not the very first AC. */
239 if (NULL
== AP
->ap_Base
)
242 ** oops, it was the very first one. I really cannot do anything for
245 FreeMem(ParsedPattern
, PatLength
);
247 UnLock(AP
->ap_Base
->an_Lock
);
248 CurrentDir(origdir
); /* stegerg */
249 FreeMem(AP
->ap_Base
, sizeof(struct AChain
));
251 return ERROR_NO_FREE_STORE
;
255 ** let me out of here. I will at least try to do something for you.
256 ** I can check the first few subdirs but that's gonna be it.
258 AP
->ap_Flags
|= APF_NOMEMERR
;
261 } /* if (NULL == AC) */
263 if (NULL
== AP
->ap_Base
)
266 if (NULL
== AP
->ap_Current
)
271 AC_Prev
->an_Child
= AC
;
273 AC
->an_Parent
= AC_Prev
;
277 ** copy the part of the pattern to the end of the AChain.
280 while (PatStart
<= PatEnd
)
282 AC
->an_String
[index
] = ParsedPattern
[PatStart
];
288 ** Put PatStart and PetEnd behind the '/' that was found.
290 PatStart
= PatEnd
+ 2;
294 ** the trailing '\0' is there automatically as I allocated enough store
298 } /* while (FALSE == AllDone) */
301 ** Free the pattern since it has been distributed now
303 FreeMem(ParsedPattern
, PatLength
);
306 ** The AnchorChain to work with is the second one.
308 AP
->ap_Base
= AP
->ap_Base
->an_Child
;
311 AC
->an_Lock
= firstlock
;
313 (void)Examine(AC
->an_Lock
, &AC
->an_Info
);
315 return followpattern(AP
, AC
, DOSBase
);
317 } /* if (NULL != ParsedPattern) */
320 return ERROR_NO_FREE_STORE
;
343 Copyright © 1995-96, The AROS Development Team. All rights reserved.
349 #include <exec/memory.h>
350 #include <exec/types.h>
352 #include <proto/exec.h>
353 #include "dos_intern.h"
355 /*****************************************************************************
358 #include <dos/dosasl.h>
359 #include <proto/dos.h>
361 AROS_LH1(LONG
, MatchNext
,
364 AROS_LHA(struct AnchorPath
*, AP
, D1
),
367 struct DosLibrary
*, DOSBase
, 138, Dos
)
370 Find next file or directory that matches a given pattern.
371 See <dos/dosasl.h> for more docs and how to control MatchNext().
375 AP - pointer to Anchor Path structure which had been passed to
385 Copying of the relative path to ap_Buf is not implemented yet
389 MatchFirst() MatchEnd() CurrentDir() Examine() ExNext()
390 ParsePattern() <dos/dosasl.h>
394 *****************************************************************************/
399 ** If the user says I am supposed to enter the directory then I first check
400 ** whether it is a directory...
403 struct AChain
* AC
= AP
->ap_Current
;
405 struct Task
* task
= FindTask(NULL
);
409 AP
->ap_BreakBits
&= (SIGBREAKF_CTRL_C
|
414 if (0 != (AP
->ap_Flags
& APF_DODIR
))
416 bug("matchnext: APF_DODIR is set\n");
417 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
418 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
420 bug("matchnext: APF_DODIR is set. Is a directory.\n");
422 /* Ok, it seems to be a directory so I will enter it. */
423 /* See whether there's a AnchorChain for that dir... */
424 if (NULL
== AC
->an_Child
)
426 bug("matchnext: APF_DODIR is set. Is a directory. Has no child. Creating temp AChain\n");
427 AC
->an_Child
= (struct AChain
*)
428 AllocVec(sizeof(struct AChain
)+1, MEMF_CLEAR
);
432 AC
->an_Child
->an_Parent
= AC
;
434 AC
->an_Child
->an_String
[0] = P_ANY
;
435 AC
->an_Child
->an_Flags
= DDF_PatternBit
;
438 bug("matchnext: Created temporary AChain structure: %x!\n", AC
->an_Child
);
441 if (NULL
!= AC
->an_Child
)
445 bug("matchnext: APF_DODIR is set. Is a directory. Has child.\n");
447 /* Ok, we're all set. */
448 /* Lock the director by it's name. */
449 AP
->ap_Current
= AC
->an_Child
;
451 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Locking \"%s\"\n", AC
->an_Info
.fib_FileName
);
453 newdir
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
454 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Lock = %x\n", newdir
);
456 if (!newdir
) /* stegerg */
462 //kprintf("CurrentDir()ing %x\n",AC->an_Info.fib_FileName);
463 (void)CurrentDir(newdir
);
464 bug("matchnext: APF_DODIR is set. Is a directory. Has child. CurrentDir()ed to lock\n");
467 AC
->an_Lock
= newdir
;
468 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Calling Examine\n");
469 Examine(AC
->an_Lock
, &AC
->an_Info
);
470 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Called Examine\n");
474 bug("matchnext: APF_DODIR is set. Could not alloc temp AChain. Returnin ERROR_NO_FREE_STORE\n");
475 return ERROR_NO_FREE_STORE
;
478 } /* if (AC->an_Info.fib_DirEntryType >= 0 ... */
480 } /* if (0 != (AP->ap_Flags & APF_DODIR )) */
482 AP
->ap_Flags
&= ~(BYTE
)(APF_DODIR
|APF_DIDDIR
);
484 bug("matchnext 2\n");
487 ** AC points to the current AnchorChain
495 ** Check for a break signal CTRL C/D/E/F
497 breakbits
= (AP
->ap_BreakBits
& SetSignal(0, 0)); /* task->tc_SigRecvd */
502 ** Finish right here... there might be a problem when/if the
503 ** algorithm is resumed the next time... Gotta test that.
505 AP
->ap_FoundBreak
= breakbits
;
506 bug("matchnext 2: break bits were set. Returning ERROR_BREAK\n");
511 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
514 while (DOSTRUE
== success
&&
515 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
516 AC
->an_Info
.fib_FileName
));
519 if (DOSFALSE
== success
)
521 bug("matchnext 2: success == DOSFALSE (no matching file)\n");
523 ** No more entries in this dir that match. So I might have to
524 ** step back one directory. Unlock the current dir first.
527 //kprintf("Couldn't find a matching file.!\n");
529 if (AP
->ap_Base
== AC
)
531 bug("matchnext 2: success == DOSFALSE (no matching file). Unlocking %x\n", AC
->an_Lock
);
533 AP
->ap_Current
= AC
->an_Parent
;
534 bug("matchnext 2: success == DOSFALSE (no matching file). AP->ap_Current = %x\n", AP
->ap_Current
);
535 bug("matchnext 2: currentdiring to %x\n", AP
->ap_Current
->an_Lock
);
536 CurrentDir(AP
->ap_Current
->an_Lock
); /* stegerg */
537 bug("matchnext 2: Cannot step back dir. Returning ERROR_NO_MORE_ENTRIES\n");
538 return ERROR_NO_MORE_ENTRIES
;
542 ** Are there any previous directories???
544 if (NULL
!= AC
&& NULL
!= AC
->an_Parent
)
548 bug("matchnext 2: success == DOSFALSE. There is a Parent and AC is *not* NULL. Unlocking %x\n", AC
->an_Lock
);
556 bug("matchnext 2: success == DOSFALSE. There is a Parent and AC is *not* NULL. CurrentDir()ing %x\n", AC
->an_Lock
);
558 CurrentDir(AC
->an_Lock
);
560 if (AC
->an_Child
->an_Flags
& DDF_PatternBit
)
562 FreeVec(AC
->an_Child
);
566 if (0 == (AC
->an_Flags
& DDF_PatternBit
))
569 ** In this case I must silently follow the pattern again...
571 bug("matchnext 2: success == DOSFALSE. DDF_PatternBit is *not* set. Leaving matchnext with result from followpattern()\n");
572 return followpattern(AP
, AC
, DOSBase
);
575 AP
->ap_Flags
|= APF_DIDDIR
;
577 ** I show this dir again as I come back from searching it
580 retval
= createresult(AP
, AC
, DOSBase
);
583 ** Step back to this directory and go on searching here
586 CurrentDir(AC
->an_Lock
);
588 if (NULL
== AC
->an_Parent
)
589 retval
= ERROR_NO_MORE_ENTRIES
;
591 bug("matchnext 2: returning retval\n", retval
);
595 } /* if (NULL != AC->an_Parent && NULL != AC) */
597 bug("matchnext 2: success == DOSFALSE. There is no Parent and/or AC is NULL. Returning ERROR_NO_MORE_ENTRIES\n");
600 ** No previous directory, so I am done here...
602 return ERROR_NO_MORE_ENTRIES
;
604 } /* if (DOSFALSE == success) */
607 bug("matchnext 2: success == DOSTRUE (found a match). Leaving matchnext wth result from createresult()\n");
608 /* Alright, I found a match... */
609 return createresult(AP
, AC
, DOSBase
);
614 bug("matchnext 2: returning 0.\n");
634 Copyright © 1995-96, The AROS Development Team. All rights reserved.
640 #include <proto/exec.h>
641 #include "dos_intern.h"
643 /*****************************************************************************
646 #include <dos/dosasl.h>
647 #include <proto/dos.h>
649 AROS_LH1(void, MatchEnd
,
652 AROS_LHA(struct AnchorPath
*, AP
, D1
),
655 struct DosLibrary
*, DOSBase
, 139, Dos
)
658 Free the memory that was allocated by calls to MatchFirst() and
662 AP - pointer to Anchor Path structure which had been passed to
666 Allocated memory is returned and filelocks are freed.
678 *****************************************************************************/
682 /* Free the AChain and unlock all locks that are still there */
683 struct AChain
* AC
= AP
->ap_Current
;
684 struct AChain
* AC_tmp
;
686 /* Unlock everything */
690 while (NULL
!= AC
->an_Parent
)
692 bug("MatchEnd: unlocking %x\n", AC
->an_Lock
);
697 bug("MatchEnd: CurrentDir(%x)\n", AC
->an_Lock
);
699 CurrentDir(AC
->an_Lock
);
701 /* AC points to the very first AChain obj. in the list */
702 /* Free the AChain List */
705 AC_tmp
= AC
->an_Child
;
712 AP
->ap_Current
= NULL
;
728 #include <exec/types.h>
729 #include <proto/exec.h>
730 #include <proto/dos.h>
731 #include <dos/dosasl.h>
732 #include "dos_intern.h"
735 LONG
followpattern(struct AnchorPath
* AP
,
737 struct DosLibrary
* DOSBase
)
741 bug("followpattern start\n");
744 ** If the user specified the pattern libs:#?/s#/
745 ** then I must enter that pattern before I return to the user.
751 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
753 while (DOSTRUE
== success
&&
754 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
755 AC
->an_Info
.fib_FileName
));
758 ** If no matching entry could be found here then I
759 ** step back one directory, unless this is the very
760 ** first directory already.
762 if (DOSFALSE
== success
)
764 bug("followpattern: success is DOSFALSE. Unlocking AC->an_Lock %x\n", AC
->an_Lock
);
769 bug("followpattern: success is DOSFALSE. AC now %x\n", AC
);
773 bug("followpattern: success is DOSFALSE. CurrentDir()ing to %x\n", AC
->an_Lock
);
775 CurrentDir(AC
->an_Lock
);
777 bug("followpattern: success is DOSFALSE. AC has parent = %s\n", AC
->an_Parent
? "yes" : "no");
779 if (NULL
== AC
->an_Parent
)
781 bug("followpattern: success is DOSFALSE. Has no parent. --> returning ERROR_NO_MORE_ENTRIES\n");
782 return ERROR_NO_MORE_ENTRIES
;
787 bug("followpattern: success *not* DOSFALSE.\n");
788 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
789 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
791 bug("followpattern: success *not* DOSFALSE. Is a directory.\n");
793 ** I must silently enter this directory if there
794 ** are further patterns left, otherwise I return to the
797 if (NULL
!= AC
->an_Child
)
800 ** Silently entering this dir according to the
805 bug("followpattern: success *not* DOSFALSE. Is a directory. Has a child. Entering\n");
807 AP
->ap_Current
= AC
->an_Child
;
809 bug("followpattern: success *not* DOSFALSE. Is a directory. Locking + CurrentDir()ing to %s\n", AC
->an_Info
.fib_FileName
);
811 newdir
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
812 bug("followpattern: success *not* DOSFALSE. Is a directory. Locking done. Lock = %x\n", newdir
);
813 (void)CurrentDir(newdir
);
815 bug("followpattern: success *not* DOSFALSE. Is a directory. CurrentDir()ing done\n");
818 AC
->an_Lock
= newdir
;
820 bug("followpattern: success *not* DOSFALSE. Is a directory. Examining lock %x\n", newdir
);
822 Examine(AC
->an_Lock
, &AC
->an_Info
);
823 bug("followpattern: success *not* DOSFALSE. Is a directory. Examining lock done\n");
827 bug("followpattern: success *not* DOSFALSE. Is a directory. Has now child. Leaving followpattern with result from createresult\n");
829 ** Ask the user whether to enter this dir or not
831 return createresult(AP
, AC
, DOSBase
);
834 } /* is a directory */
838 ** This is a file. If there is pattern left to match then
839 ** I must not show this file because I must fulfill the pattern
842 if (NULL
== AC
->an_Child
)
844 bug("followpattern: is a file and has no child: leaving followpattern with result from createresult \n");
847 ** There's no pattern left!
849 return createresult(AP
, AC
, DOSBase
);
852 bug("followpattern: Silently skipping file %s!\n",AC
->an_Info
.fib_FileName
);
856 } /* if (DOSFALSE == success) */
862 ** Hooray! A matching file was found. Also show the data in AP
864 createresult(AP
, AC
, DOSBase
);
871 ** A file/directory has been found and now it must be written
872 ** into the relevant structures.
874 LONG
createresult(struct AnchorPath
* AP
,
876 struct DosLibrary
* DOSBase
)
878 bug("createresult\n");
880 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
881 if (0 != AP
->ap_Strlen
)
883 if (FALSE
== writeFullPath(AP
))
885 bug("createresult: returning ERROR_BUFFER_OVERFLOW\n");
886 return ERROR_BUFFER_OVERFLOW
;
890 bug("createresult: done\n");
896 /* Function needed by MatchFirst/Next */
898 BOOL
writeFullPath(struct AnchorPath
* AP
)
900 struct AChain
* AC
= AP
->ap_Base
;
902 char * LastPos
= (char *)&AP
->ap_Buf
;
905 bug("writefullpath\n");
908 int len
= strlen(AC
->an_Info
.fib_FileName
);
909 if (copied
+len
> AP
->ap_Strlen
)
911 bug("writefullpath: not enough space\n");
914 strcpy(&LastPos
[copied
], AC
->an_Info
.fib_FileName
);
917 if (AC
!= AP
->ap_Current
)
920 if (copied
+1 > AP
->ap_Strlen
)
922 bug("writefullpath: not enough space 2\n");
930 if (copied
+1 > AP
->ap_Strlen
)
932 bug("writefullpath: not enough space 3\n");
935 LastPos
[copied
]='\0';
942 bug("writefullpath: done\n");