6 Copyright © 1995-2001, 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 *****************************************************************************/
70 AROS_LIBBASE_EXT_DECL(struct DosLibrary
*,DOSBase
)
73 struct AChain
* AC_Prev
= NULL
;
84 AP
->ap_Current
= NULL
;
86 PatLength
= 2*strlen(pat
)+2;
87 ParsedPattern
= AllocMem(PatLength
, MEMF_ANY
);
90 if (NULL
!= ParsedPattern
)
99 bug("matchfirst: ParsedPattern mem okay. Calling ParsePatternNoCase\n");
102 ** Put the preparsed string to some memory
103 ** If there are any wildcards then leave info
105 if (1 == ParsePatternNoCase(pat
, ParsedPattern
, PatLength
))
106 AP
->ap_Flags
|= (BYTE
)APF_ITSWILD
;
108 //bug("matchfirst: ParsePatternNoCase returned: pattern = \"%s\"\n", ParsedPattern);
111 ** First I search for the very first ':'. If a '/' comes along
112 ** before that I quit. The string before and including the ':'
113 ** is assumed to be an assigned directory, for example 'libs:'.
114 ** So I will start looking for the pattern in that directory.
118 if (ParsedPattern
[PatEnd
] == ':')
125 if ( ParsedPattern
[PatEnd
] == '/' ||
126 ParsedPattern
[PatEnd
] == '\0' ||
127 (ParsedPattern
[PatEnd
] & 0x80) != 0
128 /* a token or nonprintable letter */)
138 ** Only if success == TRUE an assigned dir was found.
143 ** try to create a lock to that assigned dir.
145 char Remember
= ParsedPattern
[PatEnd
+1];
147 ParsedPattern
[PatEnd
] = '\0';
148 firstlock
= Lock(ParsedPattern
, ACCESS_READ
);
149 origdir
= CurrentDir(firstlock
);
152 ** check whether an error occurred
154 if (NULL
== firstlock
)
156 FreeMem(ParsedPattern
, PatLength
);
157 return IoErr(); // ERROR_DIR_NOT_FOUND; /* !!! hope that's the right error code... */
161 ** I have the correct lock.
163 ParsedPattern
[PatEnd
] = Remember
;
166 } /* if (TRUE == success) */
170 ** Create a lock to the current dir.
172 origdir
= CurrentDir(NULL
);
173 firstlock
= DupLock(origdir
);
176 FreeMem(ParsedPattern
, PatLength
);
180 (void)CurrentDir(firstlock
);
183 bug("MatchFirst: origdir = %x\n", origdir
);
184 bug("MatchFirst: firstlock = %x\n", firstlock
);
187 ** Allocate an AChain structure for the original directory.
189 AC
= (struct AChain
*)AllocVec(sizeof(struct AChain
), MEMF_CLEAR
);
195 FreeMem(ParsedPattern
, PatLength
);
199 return ERROR_NO_FREE_STORE
;
202 AC
->an_Lock
= origdir
;
203 AC
->an_Flags
= DDF_Completed
|DDF_Single
;
210 ** Build the Anchor Chain. For every subdirectory I allocate
211 ** an AChain structure and link them all together
213 while (FALSE
== AllDone
)
216 ** Search for the next '/' in the pattern and everything behind
217 ** the previous '/' and before this '/' will go to an_String
221 if (ParsedPattern
[PatEnd
] == '\0')
227 if (ParsedPattern
[PatEnd
] == '/')
236 AC
= AllocVec(sizeof(struct AChain
)+(PatEnd
-PatStart
+2), MEMF_CLEAR
);
239 /* not so bad if this was not the very first AC. */
240 if (NULL
== AP
->ap_Base
)
243 ** oops, it was the very first one. I really cannot do anything for
246 FreeMem(ParsedPattern
, PatLength
);
248 UnLock(AP
->ap_Base
->an_Lock
);
249 CurrentDir(origdir
); /* stegerg */
250 FreeMem(AP
->ap_Base
, sizeof(struct AChain
));
252 return ERROR_NO_FREE_STORE
;
256 ** let me out of here. I will at least try to do something for you.
257 ** I can check the first few subdirs but that's gonna be it.
259 AP
->ap_Flags
|= APF_NOMEMERR
;
262 } /* if (NULL == AC) */
264 if (NULL
== AP
->ap_Base
)
267 if (NULL
== AP
->ap_Current
)
272 AC_Prev
->an_Child
= AC
;
274 AC
->an_Parent
= AC_Prev
;
278 ** copy the part of the pattern to the end of the AChain.
281 while (PatStart
<= PatEnd
)
283 AC
->an_String
[index
] = ParsedPattern
[PatStart
];
289 ** Put PatStart and PetEnd behind the '/' that was found.
291 PatStart
= PatEnd
+ 2;
295 ** the trailing '\0' is there automatically as I allocated enough store
299 } /* while (FALSE == AllDone) */
302 ** Free the pattern since it has been distributed now
304 FreeMem(ParsedPattern
, PatLength
);
307 ** The AnchorChain to work with is the second one.
309 AP
->ap_Base
= AP
->ap_Base
->an_Child
;
312 AC
->an_Lock
= firstlock
;
314 (void)Examine(AC
->an_Lock
, &AC
->an_Info
);
316 return followpattern(AP
, AC
, DOSBase
);
318 } /* if (NULL != ParsedPattern) */
321 return ERROR_NO_FREE_STORE
;
344 (C) 1995-96 AROS - The Amiga Research OS
350 #include <exec/memory.h>
351 #include <exec/types.h>
353 #include <proto/exec.h>
354 #include "dos_intern.h"
356 /*****************************************************************************
359 #include <dos/dosasl.h>
360 #include <proto/dos.h>
362 AROS_LH1(LONG
, MatchNext
,
365 AROS_LHA(struct AnchorPath
*, AP
, D1
),
368 struct DosLibrary
*, DOSBase
, 138, Dos
)
371 Find next file or directory that matches a given pattern.
372 See <dos/dosasl.h> for more docs and how to control MatchNext().
376 AP - pointer to Anchor Path structure which had been passed to
386 Copying of the relative path to ap_Buf is not implemented yet
390 MatchFirst() MatchEnd() CurrentDir() Examine() ExNext()
391 ParsePattern() <dos/dosasl.h>
395 *****************************************************************************/
398 AROS_LIBBASE_EXT_DECL(struct DosLibrary
*,DOSBase
)
401 ** If the user says I am supposed to enter the directory then I first check
402 ** whether it is a directory...
405 struct AChain
* AC
= AP
->ap_Current
;
407 struct Task
* task
= FindTask(NULL
);
411 AP
->ap_BreakBits
&= (SIGBREAKF_CTRL_C
|
416 if (0 != (AP
->ap_Flags
& APF_DODIR
))
418 bug("matchnext: APF_DODIR is set\n");
419 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
420 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
422 bug("matchnext: APF_DODIR is set. Is a directory.\n");
424 /* Ok, it seems to be a directory so I will enter it. */
425 /* See whether there's a AnchorChain for that dir... */
426 if (NULL
== AC
->an_Child
)
428 bug("matchnext: APF_DODIR is set. Is a directory. Has no child. Creating temp AChain\n");
429 AC
->an_Child
= (struct AChain
*)
430 AllocVec(sizeof(struct AChain
)+1, MEMF_CLEAR
);
434 AC
->an_Child
->an_Parent
= AC
;
436 AC
->an_Child
->an_String
[0] = P_ANY
;
437 AC
->an_Child
->an_Flags
= DDF_PatternBit
;
440 bug("matchnext: Created temporary AChain structure: %x!\n", AC
->an_Child
);
443 if (NULL
!= AC
->an_Child
)
447 bug("matchnext: APF_DODIR is set. Is a directory. Has child.\n");
449 /* Ok, we're all set. */
450 /* Lock the director by it's name. */
451 AP
->ap_Current
= AC
->an_Child
;
453 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Locking \"%s\"\n", AC
->an_Info
.fib_FileName
);
455 newdir
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
456 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Lock = %x\n", newdir
);
458 if (!newdir
) /* stegerg */
464 //kprintf("CurrentDir()ing %x\n",AC->an_Info.fib_FileName);
465 (void)CurrentDir(newdir
);
466 bug("matchnext: APF_DODIR is set. Is a directory. Has child. CurrentDir()ed to lock\n");
469 AC
->an_Lock
= newdir
;
470 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Calling Examine\n");
471 Examine(AC
->an_Lock
, &AC
->an_Info
);
472 bug("matchnext: APF_DODIR is set. Is a directory. Has child. Called Examine\n");
476 bug("matchnext: APF_DODIR is set. Could not alloc temp AChain. Returnin ERROR_NO_FREE_STORE\n");
477 return ERROR_NO_FREE_STORE
;
480 } /* if (AC->an_Info.fib_DirEntryType >= 0 ... */
482 } /* if (0 != (AP->ap_Flags & APF_DODIR )) */
484 AP
->ap_Flags
&= ~(BYTE
)(APF_DODIR
|APF_DIDDIR
);
486 bug("matchnext 2\n");
489 ** AC points to the current AnchorChain
497 ** Check for a break signal CTRL C/D/E/F
499 breakbits
= (AP
->ap_BreakBits
& SetSignal(0, 0)); /* task->tc_SigRecvd */
504 ** Finish right here... there might be a problem when/if the
505 ** algorithm is resumed the next time... Gotta test that.
507 AP
->ap_FoundBreak
= breakbits
;
508 bug("matchnext 2: break bits were set. Returning ERROR_BREAK\n");
513 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
516 while (DOSTRUE
== success
&&
517 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
518 AC
->an_Info
.fib_FileName
));
521 if (DOSFALSE
== success
)
523 bug("matchnext 2: success == DOSFALSE (no matching file)\n");
525 ** No more entries in this dir that match. So I might have to
526 ** step back one directory. Unlock the current dir first.
529 //kprintf("Couldn't find a matching file.!\n");
531 if (AP
->ap_Base
== AC
)
533 bug("matchnext 2: success == DOSFALSE (no matching file). Unlocking %x\n", AC
->an_Lock
);
535 AP
->ap_Current
= AC
->an_Parent
;
536 bug("matchnext 2: success == DOSFALSE (no matching file). AP->ap_Current = %x\n", AP
->ap_Current
);
537 bug("matchnext 2: currentdiring to %x\n", AP
->ap_Current
->an_Lock
);
538 CurrentDir(AP
->ap_Current
->an_Lock
); /* stegerg */
539 bug("matchnext 2: Cannot step back dir. Returning ERROR_NO_MORE_ENTRIES\n");
540 return ERROR_NO_MORE_ENTRIES
;
544 ** Are there any previous directories???
546 if (NULL
!= AC
&& NULL
!= AC
->an_Parent
)
550 bug("matchnext 2: success == DOSFALSE. There is a Parent and AC is *not* NULL. Unlocking %x\n", AC
->an_Lock
);
558 bug("matchnext 2: success == DOSFALSE. There is a Parent and AC is *not* NULL. CurrentDir()ing %x\n", AC
->an_Lock
);
560 CurrentDir(AC
->an_Lock
);
562 if (AC
->an_Child
->an_Flags
& DDF_PatternBit
)
564 FreeVec(AC
->an_Child
);
568 if (0 == (AC
->an_Flags
& DDF_PatternBit
))
571 ** In this case I must silently follow the pattern again...
573 bug("matchnext 2: success == DOSFALSE. DDF_PatternBit is *not* set. Leaving matchnext with result from followpattern()\n");
574 return followpattern(AP
, AC
, DOSBase
);
577 AP
->ap_Flags
|= APF_DIDDIR
;
579 ** I show this dir again as I come back from searching it
582 retval
= createresult(AP
, AC
, DOSBase
);
585 ** Step back to this directory and go on searching here
588 CurrentDir(AC
->an_Lock
);
590 if (NULL
== AC
->an_Parent
)
591 retval
= ERROR_NO_MORE_ENTRIES
;
593 bug("matchnext 2: returning retval\n", retval
);
597 } /* if (NULL != AC->an_Parent && NULL != AC) */
599 bug("matchnext 2: success == DOSFALSE. There is no Parent and/or AC is NULL. Returning ERROR_NO_MORE_ENTRIES\n");
602 ** No previous directory, so I am done here...
604 return ERROR_NO_MORE_ENTRIES
;
606 } /* if (DOSFALSE == success) */
609 bug("matchnext 2: success == DOSTRUE (found a match). Leaving matchnext wth result from createresult()\n");
610 /* Alright, I found a match... */
611 return createresult(AP
, AC
, DOSBase
);
616 bug("matchnext 2: returning 0.\n");
636 (C) 1995-96 AROS - The Amiga Research OS
642 #include <proto/exec.h>
643 #include "dos_intern.h"
645 /*****************************************************************************
648 #include <dos/dosasl.h>
649 #include <proto/dos.h>
651 AROS_LH1(void, MatchEnd
,
654 AROS_LHA(struct AnchorPath
*, AP
, D1
),
657 struct DosLibrary
*, DOSBase
, 139, Dos
)
660 Free the memory that was allocated by calls to MatchFirst() and
664 AP - pointer to Anchor Path structure which had been passed to
668 Allocated memory is returned and filelocks are freed.
680 *****************************************************************************/
683 AROS_LIBBASE_EXT_DECL(struct DosLibrary
*,DOSBase
)
685 /* Free the AChain and unlock all locks that are still there */
686 struct AChain
* AC
= AP
->ap_Current
;
687 struct AChain
* AC_tmp
;
689 /* Unlock everything */
693 while (NULL
!= AC
->an_Parent
)
695 bug("MatchEnd: unlocking %x\n", AC
->an_Lock
);
700 bug("MatchEnd: CurrentDir(%x)\n", AC
->an_Lock
);
702 CurrentDir(AC
->an_Lock
);
704 /* AC points to the very first AChain obj. in the list */
705 /* Free the AChain List */
708 AC_tmp
= AC
->an_Child
;
715 AP
->ap_Current
= NULL
;
731 #include <exec/types.h>
732 #include <proto/exec.h>
733 #include <proto/dos.h>
734 #include <dos/dosasl.h>
735 #include "dos_intern.h"
738 LONG
followpattern(struct AnchorPath
* AP
,
740 struct DosLibrary
* DOSBase
)
744 bug("followpattern start\n");
747 ** If the user specified the pattern libs:#?/s#/
748 ** then I must enter that pattern before I return to the user.
754 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
756 while (DOSTRUE
== success
&&
757 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
758 AC
->an_Info
.fib_FileName
));
761 ** If no matching entry could be found here then I
762 ** step back one directory, unless this is the very
763 ** first directory already.
765 if (DOSFALSE
== success
)
767 bug("followpattern: success is DOSFALSE. Unlocking AC->an_Lock %x\n", AC
->an_Lock
);
772 bug("followpattern: success is DOSFALSE. AC now %x\n", AC
);
776 bug("followpattern: success is DOSFALSE. CurrentDir()ing to %x\n", AC
->an_Lock
);
778 CurrentDir(AC
->an_Lock
);
780 bug("followpattern: success is DOSFALSE. AC has parent = %s\n", AC
->an_Parent
? "yes" : "no");
782 if (NULL
== AC
->an_Parent
)
784 bug("followpattern: success is DOSFALSE. Has no parent. --> returning ERROR_NO_MORE_ENTRIES\n");
785 return ERROR_NO_MORE_ENTRIES
;
790 bug("followpattern: success *not* DOSFALSE.\n");
791 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
792 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
794 bug("followpattern: success *not* DOSFALSE. Is a directory.\n");
796 ** I must silently enter this directory if there
797 ** are further patterns left, otherwise I return to the
800 if (NULL
!= AC
->an_Child
)
803 ** Silently entering this dir according to the
808 bug("followpattern: success *not* DOSFALSE. Is a directory. Has a child. Entering\n");
810 AP
->ap_Current
= AC
->an_Child
;
812 bug("followpattern: success *not* DOSFALSE. Is a directory. Locking + CurrentDir()ing to %s\n", AC
->an_Info
.fib_FileName
);
814 newdir
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
815 bug("followpattern: success *not* DOSFALSE. Is a directory. Locking done. Lock = %x\n", newdir
);
816 (void)CurrentDir(newdir
);
818 bug("followpattern: success *not* DOSFALSE. Is a directory. CurrentDir()ing done\n");
821 AC
->an_Lock
= newdir
;
823 bug("followpattern: success *not* DOSFALSE. Is a directory. Examining lock %x\n", newdir
);
825 Examine(AC
->an_Lock
, &AC
->an_Info
);
826 bug("followpattern: success *not* DOSFALSE. Is a directory. Examining lock done\n");
830 bug("followpattern: success *not* DOSFALSE. Is a directory. Has now child. Leaving followpattern with result from createresult\n");
832 ** Ask the user whether to enter this dir or not
834 return createresult(AP
, AC
, DOSBase
);
837 } /* is a directory */
841 ** This is a file. If there is pattern left to match then
842 ** I must not show this file because I must fulfill the pattern
845 if (NULL
== AC
->an_Child
)
847 bug("followpattern: is a file and has no child: leaving followpattern with result from createresult \n");
850 ** There's no pattern left!
852 return createresult(AP
, AC
, DOSBase
);
855 bug("followpattern: Silently skipping file %s!\n",AC
->an_Info
.fib_FileName
);
859 } /* if (DOSFALSE == success) */
865 ** Hooray! A matching file was found. Also show the data in AP
867 createresult(AP
, AC
, DOSBase
);
874 ** A file/directory has been found and now it must be written
875 ** into the relevant structures.
877 LONG
createresult(struct AnchorPath
* AP
,
879 struct DosLibrary
* DOSBase
)
881 bug("createresult\n");
883 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
884 if (0 != AP
->ap_Strlen
)
886 if (FALSE
== writeFullPath(AP
))
888 bug("createresult: returning ERROR_BUFFER_OVERFLOW\n");
889 return ERROR_BUFFER_OVERFLOW
;
893 bug("createresult: done\n");
899 /* Function needed by MatchFirst/Next */
901 BOOL
writeFullPath(struct AnchorPath
* AP
)
903 struct AChain
* AC
= AP
->ap_Base
;
905 char * LastPos
= (char *)&AP
->ap_Buf
;
908 bug("writefullpath\n");
911 int len
= strlen(AC
->an_Info
.fib_FileName
);
912 if (copied
+len
> AP
->ap_Strlen
)
914 bug("writefullpath: not enough space\n");
917 strcpy(&LastPos
[copied
], AC
->an_Info
.fib_FileName
);
920 if (AC
!= AP
->ap_Current
)
923 if (copied
+1 > AP
->ap_Strlen
)
925 bug("writefullpath: not enough space 2\n");
933 if (copied
+1 > AP
->ap_Strlen
)
935 bug("writefullpath: not enough space 3\n");
938 LastPos
[copied
]='\0';
945 bug("writefullpath: done\n");