Lock problem was:"IoErr usage"

8 posts / 0 new
Last post
JosDuchIt
JosDuchIt's picture
Offline
Last seen: 8 years 1 month ago
Joined: 2012-01-08 20:57
Lock problem was:"IoErr usage"

I have tried to modified the code below found on the net
- so as to compile for gcc
- so as tot always return a Lock on the fullpath (if it can be found) of the file that could be somewhere in the path ( i suppressed the "if (file > 0)
block)

  1. /* SAS/C compatibility
  2.  
  3. This function locates a file in the currently defined path. If the process is
  4. not a Shell process, it uses the path in effect when Workbench was loaded.
  5.  
  6. If the findpath function finds the file, it returns a lock on that directory
  7. even if it is the current directory. The lock must be unlocked with the
  8. AmigaDOS UnLock function. If the findpath function cannot find the file,
  9. it returns a -1. The value NULL is not used because NULL is a valid lock.
  10.  
  11. */
  12.  
  13. #include <proto/dos.h>
  14.  
  15. void* findpath(const char *filename)
  16. {
  17. BPTR file = Lock(filename, SHARED_LOCK);
  18.  
  19. if (file <= 0)
  20. {
  21. struct CommandLineInterface *cli = Cli();
  22. BPTR oldCurDir = CurrentDir(NULL);
  23. BPTR *paths = BADDR(cli->cli_CommandDir);
  24.  
  25. if (IoErr() == ERROR_OBJECT_IN_USE)
  26. return -1;
  27.  
  28. for (; !file && paths; paths = BADDR(paths[0]))
  29. {
  30. CurrentDir(paths[1]);
  31. file = Lock(filename, SHARED_LOCK);
  32. }
  33.  
  34. CurrentDir(oldCurDir);
  35. }
  36.  
  37. if (file > 0)
  38. {
  39. BPTR dir = ParentOfFH(file);
  40. UnLock(file);
  41. file = dir;
  42. }
  43.  
  44. return file ? file : -1;
  45. }

1. I had a strange crash in my version below, see the comments anq question marks

  1. #define __USE_INLINE__
  2. #define ZERO ((BPTR)NULL) //OS4 added
  3. #include <proto/dos.h>
  4. #include <dos/dosextens.h> /// added
  5.  
  6. BPTR findpath(const char *filename) /// filename used is Gui4Cli
  7. and we expect this file to be
  8. {
  9. struct CommandLineInterface *cli;
  10. BPTR file;
  11. BPTR *paths;
  12. BPTR oldCurDir;
  13. char dirname[200];
  14. oldCurDir = CurrentDir(ZERO);
  15. NameFromLock(oldCurDir, dirname, 180);
  16. Printf("current dir %s\n",dirname); /// prints datas:Gui4Cli, wher Gui4Cli lives
  17. Printf("filename %s\n", filename); /// prints Gui4Cli
  18. if ((file = Lock(filename, SHARED_LOCK)))
  19. { Printf("Lock ok\n"); /// not seen ???? why ?????????
  20. UnLock(file);
  21. }
  22.  
  23. if (!(file = Lock(filename, SHARED_LOCK))) /// not in the current Dir or in the path
  24. { PrintFault(IoErr(),NULL); /// no output
  25. Printf("could not lock %s\n", filename); //// this is printed out ????
  26. if ((cli = Cli()))
  27. {
  28. ///oldCurDir = CurrentDir(ZERO); // was NULL);
  29. paths = BADDR(cli->cli_CommandDir); // used to crash in some cases
  30. }
  31. if (IoErr() == ERROR_OBJECT_IN_USE) //only possible value ? why
  32. return ((BPTR)(-1)) ; //-1;
  33. ///else PrintFault(IoErr(),NULL);
  34.  
  35. for (; !file && paths; paths = BADDR(paths[0])) ///searchin in the path till Lock ok
  36. {
  37. CurrentDir(paths[1]);
  38. file = Lock(filename, SHARED_LOCK); ///>>>>> crash here now
  39. }
  40.  
  41. CurrentDir(oldCurDir); // the original current directory
  42. }
  43.  
  44.  
  45. return file ? file : ((BPTR)(-1));//-1;
  46. }

Maybe there is an explanation in the code above, that i don't see. I hope so.
Otherwise it may be due to the following :
findpath() is used in the Gui4Cli launcher (name 'Gui' gui.c source is available) which uses Olaf Barthel's wbpath.c that Thomas was able to dig out.
findpath() could be a SAS/C provided function. The findpath.c is my reconstruction based on a non SAS/C findpath.c source.
If somebody has the latter source that would help too of course

2. I wondered for the first source what IoErr() really could detect. (where a significant IoErr() was set. Indeed, the autodocs neither for Lock() Cli() nor CurrentDir() mention even IoErr().

thomas
thomas's picture
Offline
Last seen: 1 week 17 hours ago
Joined: 2011-05-16 14:23
I don't know why it crashes.

I don't know why it crashes. But I see this:

1. you set CurrentDir to ZERO and then wonder why it is still zero whyn you call it again?
2. you search the file in the current dir while current dir is zero. This will always fail. If the file *is* in the (old) current dir, then the function will not find it
3. why do you return -1 in case of failure? How do you check for failure in your main program? If you return -1 you need to check for -1.

Here is a reworked version:

  1. #include <proto/dos.h>
  2.  
  3. #ifndef __amigaos4__
  4. struct PathNode {
  5. BPTR pn_Next;
  6. BPTR pn_Lock;
  7. };
  8. #endif
  9.  
  10. BPTR findpath (const char *filename)
  11.  
  12. {
  13. BPTR file = Lock(filename, SHARED_LOCK);
  14.  
  15. if (!file)
  16. {
  17. struct CommandLineInterface *cli;
  18. BPTR oldCurDir;
  19. struct PathNode *paths;
  20.  
  21. if (IoErr() == ERROR_OBJECT_IN_USE) // Lock() failed because file is in use
  22. return (BPTR)0;
  23.  
  24. cli = Cli();
  25.  
  26. oldCurDir = CurrentDir((BPTR)0);
  27.  
  28. for (paths = BADDR(cli->cli_CommandDir); !file && paths; paths = BADDR(paths->pn_Next))
  29. {
  30. CurrentDir(paths->pn_Lock);
  31. file = Lock(filename, SHARED_LOCK);
  32. }
  33.  
  34. CurrentDir(oldCurDir);
  35. }
  36.  
  37. if (file)
  38. {
  39. BPTR dir = ParentDir(file); // file is a lock, not a fh
  40. UnLock(file);
  41. file = dir;
  42. }
  43.  
  44. return (file ? file : (BPTR)0);
  45. }
  46.  
  47.  
  48. int main (void)
  49.  
  50. {
  51. struct RDArgs *rdargs = NULL;
  52. struct {
  53. char *file;
  54. } args;
  55. BPTR path;
  56.  
  57. rdargs = ReadArgs ("FILE/A",(APTR)&args,NULL);
  58. if (!rdargs)
  59. {
  60. PrintFault (IoErr(),NULL);
  61. return (RETURN_ERROR);
  62. }
  63.  
  64. path = findpath (args.file);
  65. if (path)
  66. {
  67. char buffer[256];
  68.  
  69. NameFromLock (path,buffer,256);
  70. Printf ("%s found in %s\n",args.file,buffer);
  71.  
  72. UnLock (path);
  73. }
  74. else
  75. Printf ("cannot find %s\n",args.file);
  76.  
  77. FreeArgs (rdargs);
  78.  
  79. return (RETURN_OK);
  80. }

Note that it still has at least two flaws:

1. it also finds directories
2. it does not handle multi-assigns, so it does not find files in further components of C:.

JosDuchIt
JosDuchIt's picture
Offline
Last seen: 8 years 1 month ago
Joined: 2012-01-08 20:57
@Thomas, thanks for your

@Thomas, thanks for your help.

The problem is not solved yet though, when using my gui4 launcher as standard tool to a Gui4Cli sscript's icon on line 28

It works OK when launched from shell
>> gui4 Myscript.gc // Myscript.gc is in the same directory
>> gui4 Mypath/Myscript.gc

I'll investigate further

salass00
salass00's picture
Offline
Last seen: 7 months 1 week ago
Joined: 2011-02-03 11:27
@JosDuchIt When you run the

@JosDuchIt

When you run the program from Workbench Cli() will return a NULL pointer because the program doesn't have a CLI structure causing NULL pointer accesses later in your program since you don't check the return value from this function before using it.

thomas
thomas's picture
Offline
Last seen: 1 week 17 hours ago
Joined: 2011-05-16 14:23
The problem is not solved yet

The problem is not solved yet though, when using my gui4 launcher as standard tool to a Gui4Cli sscript's icon on line 28

May I ask what you try to use this routine for? If you use your program as default tool in a project icon, then sm_ArgList[0] points to program and sm_ArgList[1] points to the script. What do you search in the path?

JosDuchIt
JosDuchIt's picture
Offline
Last seen: 8 years 1 month ago
Joined: 2012-01-08 20:57
@salass00 Thanks for help.

@salass00
Thanks for help. That explains the crash when i use findäth() from thomas example & his main()

However the original source gui4.c is compiled together with findpath.c and wbpath.c (provided by thomas too)
Main() therefor begins with

  1. /*--------------------------- If started from WB -------------------
  2. if (!argc)
  3. { outpt = 1; /* always open output window */
  4. WBSTART=1;
  5. if (!(WorkbenchBase = (struct Library *)OpenLibrary("workbench.library", 37L)))
  6. goto endprog;
  7. path = CloneWorkbenchPath((struct WBStartup *)argv); /// cloned version of Workbench »Execute Command ...«'s path

and later has the lines

  1. /*------------------------- PASS to other Gui4Cli if running, else startup -----------*/
  2.  
  3. if (!(host = FindPort(portname))) /* not found - launch it */
  4. {
  5. // look for Gui4Cli in the current path
  6. Printf("going to find path\n");
  7. if ((gcprog = (BPTR)findpath("Gui4Cli")) != ((BPTR)-1)) /// that's why my version of findpath
  8. uses theis return value
  9. { UnLock (gcprog);
  10. strcpy (comline, "Gui4Cli "); ///Gui4Cli is in the path
  11. Printf ("0 %s\n", comline);
  12. }
  13. else
  14. { if ((gcprog = Lock("GUIs:Gui4cli", ACCESS_READ))) ////
  15. { UnLock (gcprog);
  16. strcpy (comline, "GUIs:Gui4Cli ");
  17. Printf ("1 %s\n", comline);
  18. }
  19. else
  20. { Write (Output(), "Gui4Cli not found!", 18);
  21. goto endprog;
  22. }
  23. }

and later

  1. // launch program
  2. if (WBSTART == 0) /* started from cli */
  3. { PROGret = (LONG)SystemTags(comline, SYS_Asynch, TRUE, SYS_Input, NULL,
  4. SYS_Output, NULL, TAG_END);
  5. }
  6. else /* started from WB */
  7. { PROGret = (LONG)SystemTags(comline, SYS_Asynch, TRUE, SYS_Input, NULL,
  8. SYS_Output, NULL, NP_Path, path, TAG_DONE);
  9. if (PROGret == -1) FreeWorkbenchPath(path);
  10. }
  11. if (PROGret == -1) PROGret = 20;

I still have the crash as if the path was not known to findpath.
I am of course not sure if the gui4 source i inherited was correct
and if the reconstructed findpath() is doing what is expected.
Thinking about your remark:
shouldn't findpath() get the cloned 'path' as argument?
(obviously the original gui4source does not think so.)

wbpath.h states:

When a program is launched via the »Execute Command ...«
menu item provided by Workbench, Workbench passes the CLI
command path that was active at the time LoadWb was invoked
to the application. Regular Workbench processes, however, do
not operate in a CLI environment, so they cannot inherit the
Workbench path, and new shells spawned by such processes via
SystemTagList() start with an »empty« path (i.e. just »C:«
and the current directory).

The function CloneWorkbenchPath() creates a local copy of
the current Workbench path, usually for the purpose of it
being passed to SystemTagList() or to CreateNewProc() via
the NP_Path tag; the WBStartup parameter passed to
CloneWorkbenchPath() must be valid and non-NULL. The path is
deallocated automatically by the OS upon the termination of
the newly created process; if the CreateNewProc() or
SystemTagList() call fails, however, the cloned path must be
freed explicitly by calling FreeWorkbenchPath().

salass00
salass00's picture
Offline
Last seen: 7 months 1 week ago
Joined: 2011-02-03 11:27
The reason it doesn't work is

The reason it doesn't work is that while you use CloneWorkbenchPath to clone the WB path, in findpath() you're still trying to get the path from the CLI structure which doesn't exist because your program was started from WB.

What you need to do is change this:

  1. cli = Cli();
  2.  
  3. oldCurDir = CurrentDir((BPTR)0);
  4.  
  5. for (paths = BADDR(cli->cli_CommandDir); !file && paths; paths = BADDR(paths->pn_Next))
  6. {
  7. CurrentDir(paths->pn_Lock);
  8. file = Lock(filename, SHARED_LOCK);
  9. }
  10.  
  11. CurrentDir(oldCurDir);

so that it uses a cloned WB path if CLI structure isn't available:

  1. BPTR pathlist;
  2.  
  3. cli = Cli();
  4.  
  5. if (cli)
  6. {
  7. pathlist = BADDR(cli->cli_PathList);
  8. } else {
  9. pathlist = WBPath; /* use value returned from CloneWorkbenchPath() */
  10. }
  11. if (pathlist) /* better safe than sorry */
  12. {
  13. oldCurDir = GetCurrentDir();
  14.  
  15. for (paths = BADDR(pathlist); !file && paths; paths = BADDR(paths->pn_Next))
  16. {
  17. CurrentDir(paths->pn_Lock);
  18. file = Lock(filename, SHARED_LOCK);
  19. }
  20.  
  21. CurrentDir(oldCurDir);
  22. }
JosDuchIt
JosDuchIt's picture
Offline
Last seen: 8 years 1 month ago
Joined: 2012-01-08 20:57
@salas00 Many thanks, that

@salas00
Many thanks, that did it.
@thomas too for all your help
Endresult

  1.  
  2. #define __USE_INLINE__
  3. #define ZERO ((BPTR)0)
  4. #include <proto/dos.h>
  5. #ifndef __amigaos4__
  6. struct PathNode {
  7. BPTR pn_Next;
  8. BPTR pn_Lock;
  9. };
  10. #endif
  11. BPTR findpath (const char *filename, BPTR WBpath )
  12. {
  13. BPTR oldCurDir = CurrentDir(ZERO);
  14. char dirname[200];
  15. BPTR pathlist;
  16. BPTR file = Lock(filename, SHARED_LOCK);
  17. if (!file)
  18. {
  19. struct CommandLineInterface *cli;
  20. struct PathNode *paths; ///
  21. if (IoErr() == ERROR_OBJECT_IN_USE) // Lock() failed because file is in use
  22. return (BPTR)-1;
  23.  
  24. cli = Cli();
  25. if (cli)
  26. {
  27. pathlist = cli->cli_PathList;
  28. }
  29. else
  30. {
  31. pathlist = WBpath; /* use value returned from CloneWorkbenchPath() */
  32. }
  33. if (pathlist) /* better safe than sorry */
  34. {
  35. oldCurDir = CurrentDir(ZERO);
  36. for (paths = BADDR(pathlist); !file && paths; paths = BADDR(paths->pn_Next))
  37. {
  38. CurrentDir(paths->pn_Lock);
  39. file = Lock(filename, SHARED_LOCK);
  40. }
  41. CurrentDir(oldCurDir);
  42. }
  43. }
  44. return (file ? file : (BPTR)-1);
  45. }
Log in or register to post comments