[comp.sys.amiga.tech] Changing Directories

SLMYQ@USU.BITNET (04/06/88)

Here are some hints for changing the current directory in a program.

First of all, just using CurrentDir(newdir) IS ABSOLUTELY NO GOOD.  It will
lose 24 bytes of memory each time, because you didn't free the lock on the
old directory.  Although 24 bytes isn't much, think of how many times you
might be changing the current directory.  You need to UnLock the lock returned
by CurrentDir().  However, remember that CurrentDir() *might* not return
a lock - just a NULL, if you're changing the directory from the initial
startup directory to something else.  My suggestion is to create a routine
like this and always use it to change directories.

VOID ChangeDir(NewDir)
BPTR NewDir;
{
        BPTR OldDir;

        if ((OldDir = (BPTR)CurrentDir(NewDir)) != NULL)
                UnLock(OldDir);
}

Next suggestion.  Unless you are writing a CD program, you really should
save and restore the old current directory, so if you start a program from
the CLI in one directory, you don't wind up in another directory afterwards.
However, if you use the ChangeDir() routine above, beware that it is not
enough that you simply save the old lock pointer.  If you did this, then
the first time you did a ChangeDir(), that lock would be freed, and your
pointer would become invalid. You need to DupLock() that lock, and save it.
Then after the program is finished, just ChangeDir() to the duplicate lock.

Final suggestion.  This is merely to avoid confusion.  Put a few lines at
the beginning of your program like this:

        struct Process *MyProcess = FindTask(NULL);

        if (MyProcess->pr_CurrentDir == NULL) {
                ChangeDir(Lock("SYS:",ACCESS_READ));
        }

Of course, you really should check to make sure the lock returned by the Lock()
call actually succeeded.

Now if you're wondering why the current directory could possibly be zero,
it's because of one of those weird things in AmigaDOS.  When a process is
first created, its pr_CurrentDir is set to zero, rather than some specific
lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.
For your programs, it would probably be easier just to get a *real* lock on
the SYS: directory and set it to that, and then you don't have to worry about
yourself being nowhere at all. :)

Hope this helps, and I hope I stop seeing programs losing memory every time
they run :)

                                Bryan

        Bryan Ford                    //// A computer does what \\\\
Snail:  1790 East 1400 North         //// you tell it to do, not \\\\
        Logan, UT 84321          \\\X///  what you want it to do. \\\X///
Email:  SLMYQ@USU.BITNET          \XXX/ Murphy's Law Calendar 1986 \XXX/

avery@puff.cs.wisc.edu (Aaron Avery) (04/08/88)

In article <8804060734.AA13918@jade.berkeley.edu> SLMYQ@USU.BITNET writes:
>Here are some hints for changing the current directory in a program.
Good ideas, thanks for posting them.

>Next suggestion.  Unless you are writing a CD program, you really should
>save and restore the old current directory, so if you start a program from
Very true. Here's what I do:
At the beginning of my program, I do:

curdir = DupLock(FindTask(NULL)->pr_CurrentDir);
firstdir = CurrentDir(curdir);

So now I have firstdir available to CurrentDir to at the end of my program.
Now, since _I_ allocated curdir, I can use:

curdir = newdir;
UnLock(CurrentDir(curdir));

to move to a new directory. This is, of course, after checking that newdir
is valid and is a directory. At the end of my program I just:

UnLock(CurrentDir(firstdir));

and I'm back!

One note:
curdir = Lock("", ACCESS_READ); can be used in place of the above DupLock().

>Now if you're wondering why the current directory could possibly be zero,
>it's because of one of those weird things in AmigaDOS.  When a process is
>first created, its pr_CurrentDir is set to zero, rather than some specific
>lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.
Are you sure about this? When you 'run <programname>', the newly created
process has whatever current directory the shell it was invoked from has.
But I do believe that if you never switched directories in your original
shell, what you said above is true.


-- 
Aaron Avery (avery@puff.cs.wisc.edu)
	    ({seismo,caip,allegra,harvard,rutgers,ihnp4}!uwvax!puff!avery)

dillon@CORY.BERKELEY.EDU (Matt Dillon) (04/08/88)

>>first created, its pr_CurrentDir is set to zero, rather than some specific
>>lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.
>Are you sure about this? When you 'run <programname>', the newly created
>process has whatever current directory the shell it was invoked from has.
>But I do believe that if you never switched directories in your original
>shell, what you said above is true.

	It happens often.

					-Matt

SLMYQ@USU.BITNET (04/09/88)

>>Next suggestion.  Unless you are writing a CD program, you really should
>>save and restore the old current directory, so if you start a program from
>Very true. Here's what I do:
>At the beginning of my program, I do:
>
>curdir = DupLock(FindTask(NULL)->pr_CurrentDir);
>firstdir = CurrentDir(curdir);

Yeah, that's another way to do it, although it seems you could just have:

firstdir = DupLock(FindTask(NULL)->pr_CurrentDir);

Then the new lock would be the one you would save until the end of the
program, and the original one would be the "working" lock.  The only
difference is that it saves the CurrentDir().

>So now I have firstdir available to CurrentDir to at the end of my program.
>Now, since _I_ allocated curdir, I can use:
>
>curdir = newdir;
>UnLock(CurrentDir(curdir));

Or how about just UnLock(CurrentDir(newdir))?
Or better yet, like I did, define a function that only UnLock()s it if
it's non-zero - I called it ChangeDir().

>to move to a new directory. This is, of course, after checking that newdir
>is valid and is a directory. At the end of my program I just:
>
>UnLock(CurrentDir(firstdir));
>
>and I'm back!
>
>One note:
>curdir = Lock("", ACCESS_READ); can be used in place of the above DupLock().

Interesting.  I wonder which has more overhead?

>>Now if you're wondering why the current directory could possibly be zero,
>>it's because of one of those weird things in AmigaDOS.  When a process is
>>first created, its pr_CurrentDir is set to zero, rather than some specific
>>lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.
>Are you sure about this? When you 'run <programname>', the newly created
>process has whatever current directory the shell it was invoked from has.
>But I do believe that if you never switched directories in your original
>shell, what you said above is true.

Oh, yeah, that's right.  However, if you boot up the Amiga, press CTRL-D
before anything can get going, and run a program, that program's
pr_CurrentDir *will* be zero.  I've had a lot of trouble with this -
my programs aborted with out-of-memory errors because they couldn't
DupLock() a zero lock!

Try this:

#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

main()
{
        printf("pr_CurrentDir: %ld",((struct Process*)FindTask(NULL))->
                pr_CurrentDir);
}

This is just off the top of my head, so I don't guarantee that it's bug-free.
If it works as expected, when you run it before CDing anywhere, it'll show
0.  After you CD to somewhere, it'll show you some value.

>--
>Aaron Avery (avery@puff.cs.wisc.edu)
>            ({seismo,caip,allegra,harvard,rutgers,ihnp4}!uwvax!puff!avery)

                                Bryan Ford (SLMYQ@USU.BITNET)

peter@sugar.UUCP (Peter da Silva) (04/12/88)

>first created, its pr_CurrentDir is set to zero, rather than some specific
>lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.

Actually, the zero lock assumes the boot device. Unless you never reassign
sys: and never do anything with your boot disk then this is not guaranteed
to be sys:.
-- 
-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.

spencer@eris (Randal m. Spencer [RmS]) (04/13/88)

Recently on *comp.sys.amiga.tech* peter@sugar.UUCP (Peter da Silva) wrote:

...Actually, the zero lock assumes the boot device. Unless you never reassign
...sys: and never do anything with your boot disk then this is not guaranteed
...to be sys:.
...-- 
...-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter

Are you sure, I believe that it always comes out to be DF0:.  When I boot
from another device (can't imagine what that would be:'), and I do a CD it
says "DF0:".  
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Randy Spencer      P.O. Box 4542   Berkeley  CA  94704        (415)222-7595 
spencer@mica.berkeley.edu        I N F I N I T Y         BBS: (415)222-9416
..ucbvax!mica!spencer            s o f t w a r e                  AAA-WH1M
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

SLMYQ@USU.BITNET (04/15/88)

>>first created, its pr_CurrentDir is set to zero, rather than some specific
>>lock.  With the BCPL commands, this zero lock "assumes" the SYS: directory.
>
>Actually, the zero lock assumes the boot device. Unless you never reassign
>sys: and never do anything with your boot disk then this is not guaranteed
>to be sys:.

Great.  So how can you tell what the system was booted off?  I didn't think
AmigaDOS would make it that easy! :)

                                Bryan Ford (SLMYQ@USU.BITNET)

peter@sugar.UUCP (Peter da Silva) (04/15/88)

In article ... spencer@eris (Randal m. Spencer [RmS]) writes:
> Recently on *comp.sys.amiga.tech* peter@sugar.UUCP (Peter da Silva) wrote:
> ...Actually, the zero lock assumes the boot device. Unless you never reassign
> ...sys: and never do anything with your boot disk then this is not guaranteed
> ...to be sys:.

> Are you sure, I believe that it always comes out to be DF0:.  When I boot
> from another device (can't imagine what that would be:'), and I do a CD it
> says "DF0:".  

Well, not having a self-booting device other than DF0:, I just believed the
docs that said that's what it was.

AmigaDOS technical reference manual, page whatever. Under "CurrentDir":

"A value of zero is a valid result here and indicates that the current
directory is the root of the initial startup disk."

It's a pity that the REST of the system isn't set up to reflect this and
treat 0 as df0: or a no-op. It's a bit of a shocker to guru because you've
Unlock()ed CurrentDir().
-- 
-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.

cmcmanis%pepper@Sun.COM (Chuck McManis) (04/16/88)

In article <1838@sugar.UUCP> peter@sugar.UUCP (Peter da Silva) writes:
>It's a pity that the REST of the system isn't set up to reflect this and
>treat 0 as df0: or a no-op. It's a bit of a shocker to guru because you've
>Unlock()ed CurrentDir().

Have you crashed because you sent UnLock a 0? I seem to recall writing some
code that just assumed everything worked as expected and it seemed to do
the right thing. Of course I don't know if I ran it from the Initial
CLI or not. 

--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.

peter@sugar.UUCP (Peter da Silva) (04/17/88)

In article <49692@sun.uucp>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes:
> Have you crashed because you sent UnLock a 0?

I don't recall. I'm not inclined to try the experiment right this instant,
but the documentation seemed to say that this was a no-no.
-- 
-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.

andy@cbmvax.UUCP (Andy Finkel) (04/18/88)

In article <1838@sugar.UUCP> peter@sugar.UUCP (Peter da Silva) writes:
>It's a pity that the REST of the system isn't set up to reflect this and
>treat 0 as df0: or a no-op. It's a bit of a shocker to guru because you've
>Unlock()ed CurrentDir().

The general rule to follow here is don't be unlocking things that you
haven't locked.  If you lock currentdir you can unlock the lock
you get back.  You can't unlock that was there previously, as you
don't have a lock on it.

		andy
-- 
andy finkel		{ihnp4|seismo|allegra}!cbmvax!andy 
Commodore-Amiga, Inc.

"C combines the power of assembly language with the flexibility of
 assembly language."
		
Any expressed opinions are mine; but feel free to share.
I disclaim all responsibilities, all shapes, all sizes, all colors.

peter@sugar.UUCP (Peter da Silva) (04/18/88)

In article <3640@cbmvax.UUCP>, andy@cbmvax.UUCP (Andy Finkel) writes:
> The general rule to follow here is don't be unlocking things that you
> haven't locked.  If you lock currentdir you can unlock the lock
> you get back.  You can't unlock that was there previously, as you
> don't have a lock on it.

Haven't we been through this one already?

I'm pretty sure C:CD unlocks a directory it never got a lock on in the
first place, but you're the expert.

I certainly can't think of any way to write a CD replacement that doesn't
do something like this...
-- 
-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.

dpvc@ur-tut (Davide P. Cervone) (04/19/88)

In article <8804150317.AA26694@jade.berkeley.edu> SLMYQ@USU.BITNET writes:
>>Actually, the zero lock assumes the boot device. Unless you never reassign
>>sys: and never do anything with your boot disk then this is not guaranteed
>>to be sys:.
>
>Great.  So how can you tell what the system was booted off?  I didn't think
>AmigaDOS would make it that easy! :)

You can call Info() with this lock to find out stuff about the device.  Or
you can call DupLock() to get a non-zero lock on the same device, and use the
pointers it contains to find it in the device list (it's been over a year
since I've done this kind of thing, so I can't be more specific).

Davide P. Cervone
dpvc@tut.cc.rochester.edu
dpvc@ur-tut.UUCP
DPVC@UORDBV.BITNET

andy@cbmvax.UUCP (Andy Finkel) (04/19/88)

In article <1863@sugar.UUCP> peter@sugar.UUCP (Peter da Silva) writes:
>In article <3640@cbmvax.UUCP>, andy@cbmvax.UUCP (Andy Finkel) writes:
>Haven't we been through this one already?
>
>I'm pretty sure C:CD unlocks a directory it never got a lock on in the
>first place, but you're the expert.

Don't know.  Anyway, c:CD checks to see if the lock is 0
before freeing (unlocking) it.

			andy
-- 
andy finkel		{ihnp4|seismo|allegra}!cbmvax!andy 
Commodore-Amiga, Inc.

"C combines the power of assembly language with the flexibility of
 assembly language."
		
Any expressed opinions are mine; but feel free to share.
I disclaim all responsibilities, all shapes, all sizes, all colors.

morgan@brambo.UUCP (Morgan W. Jones) (04/20/88)

In article <8804150317.AA26694@jade.berkeley.edu> SLMYQ@USU.BITNET writes:
>Great.  So how can you tell what the system was booted off?  I didn't think
>AmigaDOS would make it that easy! :)

You shouldn't!  It isn't any program's business to know what the boot
device was.  If you really need to know, ask.

All we need is more software that doesn't let the user control it's
operation.

>                                Bryan Ford (SLMYQ@USU.BITNET)

-- 
Morgan Jones - Bramalea Software Inc.        morgan@brambo.UUCP
      ...!{uunet!mnetor!lsuc!ncrcan, utgpu!telly}!brambo!morgan
"These might not even be my opinions, let alone anyone else's."

SLMYQ@USU.BITNET (04/23/88)

>>Great.  So how can you tell what the system was booted off?  I didn't think
>>AmigaDOS would make it that easy! :)
>
>You shouldn't!  It isn't any program's business to know what the boot
>device was.  If you really need to know, ask.
>
>All we need is more software that doesn't let the user control it's
>operation.

Really now.  I can tell you haven't been following this discussion too
closely.  You're right that programs should'nt need to know what the
system was booted off of - usually.

The only time when you need to know is when AmigaDOS gives you one of
those crazy NULL locks as a current directory.  They're hard to work
with, to say the least. :) They refer to the boot device, and all I
want is to be able to get a *real* lock on the boot device when I find
one of those NULL locks, and switch over to that.  The only time this
would happen is if the user booted up the system, pressed CTRL-D before
anything could happen in the startup-sequence, and ran a program.  That
program would get a NULL lock as it's current directory.  Not too handy.

>Morgan Jones - Bramalea Software Inc.        morgan@brambo.UUCP

                                Bryan

dpvc@ur-tut (Davide P. Cervone) (05/03/88)

In article <8804230242.AA03176@jade.berkeley.edu> SLMYQ@USU.BITNET writes:
>The only time when you need to know is when AmigaDOS gives you one of
>those crazy NULL locks as a current directory.  They're hard to work
>with, to say the least. :) They refer to the boot device, and all I
>want is to be able to get a *real* lock on the boot device when I find
>one of those NULL locks, and switch over to that.
>                                Bryan

Why don't you call DupLock() on the NULL lock, and then use the lock that it
returns?  I recall using this trick way back in version 1.0 days, and I think 
it worked, since (as I understand it), DupLock() is guaranteed to return
a pointer to a newly created lock on the same structure; i.e., it can NOT
be the NULL lock, since that one already exists.  Anyway, it got me out of that
trouble back when I was messing with the DevInfo structures.

Hope this helps.

Davide P. Cervone
dpvc@tut.cc.rochester.edu
dpvc@ur-tut.UUCP
DPVC@UORDBV.BITNET