paths

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

paths

Post by Alberto »

Hi all,

sorry to ask maybe a stupid question, but I'm dealing with paths and filenames, and would like to know if there si a function for expanding a relative path to an absolute one.
I'm "pretty" new to the "C" language, and after having find'd grep'd the pspdsk and the internet with my friend google, I haven't came across anything...

Something like the Borland Pascal FExpand, that for "./currentfolder/../common/fonts" should return "ms0:/PSP/GAME/MYSW/common/fonts", provided the current working directory was "ms0:/PSP/GAME/MYSW".

Thank you for any tips, I would like to avoid writing one from scrap... ;-)

Cheers, A.
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

I don't know if there's a function that returns the current working directory path (like pwd on *IX systems), but your application should just keep track of the current directory, it's easier and cleaner.
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
Zer01ne
Posts: 28
Joined: Mon Sep 08, 2008 7:15 am

Post by Zer01ne »

Code: Select all

sceIoChdir("ms0:/PSP/GAME/MYSW/");
This function change the current directory to the directory "ms0:/PSP/GAME/MYSW/"
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

Thank you both for the answer.
actually, I don't need to change the directory, so sceIoChdir has no use for me.
Finally I ended up writing a function from scratch; it _does_ know the base folder to use in case of relative paths (the running folder I can get from argv[0], and that would eventually change, shall I adopt any Chdir...), and returns a fully qualified absolute path, from the "ms0:/" and on.

First, I split the path in its components and fill a list with them (adds a little overhead, but at the end is a lot easier to use). Then I just remove the ".." entries together with the previous one. The "." entries are just removed.
Finally I just repack the path.

In the graphical "open file dialog" I made, if I reach a root, where ".." isn't there, I just add it to the "list", and when applying it to a root, I just clean and fill the list only with devices like "ms0:/", "host0:/" etc.

Works good for what are my needs.
It took me a day, but a good 50% was for the graphical part, icons, etc.

Cheers, A.
jsharrad
Posts: 100
Joined: Thu Oct 20, 2005 3:06 am

Post by jsharrad »

If you're using newlib you can just getCwd(); if not then yeah getting it from argv[0] is what I do too.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Use realpath:

Code: Select all

char buf[MAXPATHLEN];
if (realpath("../", buf) != NULL) {
   printf("the absolute path is %s\n", buf);
}
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

jimparis wrote:Use realpath:

Code: Select all

char buf[MAXPATHLEN];
if (realpath("../", buf) != NULL) {
   printf("the absolute path is %s\n", buf);
}
good find... thou' I'm not able to compile: 'realpath' was not declared in this scope. Including either stdlib.h or unistd.h, same thing.
Where is it defined?

Thanks, A.
carl0sgs
Posts: 33
Joined: Thu Dec 10, 2009 3:51 am
Contact:

Post by carl0sgs »

I think this is what you need:

Code: Select all

#include <dirent.h> // for getcwd
char buffer&#91;601&#93;;
getcwd&#40;buffer, 600&#41;;
(not sure of the values 600 & 601)

Hope it is useful
User avatar
Coldbird
Posts: 97
Joined: Thu Feb 08, 2007 7:22 am

Post by Coldbird »

I just wanna note that relying on argv[0] for boot path checks isn't a clever idea as the OFW isn't providing anything of the sort when loading modules (the argument isnt given!).

So if you rely on argv[0] to get your path you will run into trouble if you run your module from flash0 using pspbtcnf loading lists...

If you only intend to run your modules on "sane areas" - like cfw ms0 loaders (game.txt, etc...) or using your own prx loader that provides argv[0] for you then its fine though.

But I must admit I'm doing it the same way, grabbing from argv[0] whenever possible.

I'm sure though there just has to be a function to grab the cwd natively built into the PSP firmware... probably somewhere in sascore or something...
Been gone for some time. Now I'm back. Someone mind getting me up-2-date?
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

There is sceIoGetThreadCwd but annoyingly it is kernel mode only from what I remember. This is why the C library maintains its own copy based on argv[0] but as that doesn't have to match where the file really comes from it isn't ideal.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

I thought even official games used hardcoded paths for custom memory stick data?
carl0sgs
Posts: 33
Joined: Thu Dec 10, 2009 3:51 am
Contact:

Post by carl0sgs »

carl0sgs wrote:I think this is what you need:

Code: Select all

#include <dirent.h> // for getcwd
char buffer&#91;601&#93;;
getcwd&#40;buffer, 600&#41;;
(not sure of the values 600 & 601)

Hope it is useful
I repeat, getcwd() works for me.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Alberto wrote:
jimparis wrote:Use realpath:

Code: Select all

char buf&#91;MAXPATHLEN&#93;;
if &#40;realpath&#40;"../", buf&#41; != NULL&#41; &#123;
   printf&#40;"the absolute path is %s\n", buf&#41;;
&#125;
good find... thou' I'm not able to compile: 'realpath' was not declared in this scope. Including either stdlib.h or unistd.h, same thing.
Where is it defined?

Thanks, A.
It's in newlib, but I think it's missing from the header file. Just add its prototype:

Code: Select all

char *realpath&#40;const char *path, char *resolved_path&#41;;
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

jimparis wrote:It's in newlib, but I think it's missing from the header file. Just add its prototype:

Code: Select all

char *realpath&#40;const char *path, char *resolved_path&#41;;
sorry to bug, now I do get it compiled, but get "undefined reference to realpath"

I just defined the prototype at the beginning of the main.c, just to test it.
I'm new to C when it comes to these things, so maybe I'm still missing something? Any library to include (apart from the -lc which gets included by build.mak)?

Thanks in advance,
A.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

It's there... maybe you have an old newlib or you're using psplibc or something. try:

Code: Select all

psp-nm /usr/local/pspdev/psp/lib/libc.a | grep realpath
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

jimparis wrote:It's there... maybe you have an old newlib or you're using psplibc or something. try:

Code: Select all

psp-nm /usr/local/pspdev/psp/lib/libc.a | grep realpath
this is what I got:

realpath.o:
00000000 T realpath

Don't have a clue of what this may mean, but looks like I have it...
so I need to compile the application with USE_PSPSDK_LIBC = 1 in the makefile?

I'm asking, because if I do so, I get a lot of undefined references to opendir, readdir, closedir... and some undefined references to _impure_ptr_, plus something else...

Any help?

Thanks, A.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Nope, don't USE_PSPSDK_LIBC. Your grep shows that realpath is defined in libc, so either you're compiling against the wrong libc or something else. Post the full output of your compilation, maybe we can see what's wrong.
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

Ok,

let me arrange a smaller app that gives me the errors and I'll post everything later on, today.

Thanks for the support,
A.
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

here's the compilation log (hope it's what you asked)

Code: Select all

rm -f empty.elf empty.prx  main.o  /home/batman/Projects/PSP/library/utils.o /home/batman/Projects/PSP/library/fileutils.o  /home/batman/Projects/PSP/psplib/pspapplication.o /home/batman/Projects/PSP/psplib/pspcrt.o  PARAM.SFO EBOOT.PBP EBOOT.PBP
psp-g++ -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o main.o main.cpp
psp-g++ -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o /home/batman/Projects/PSP/library/utils.o /home/batman/Projects/PSP/library/utils.cpp
psp-g++ -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o /home/batman/Projects/PSP/library/fileutils.o /home/batman/Projects/PSP/library/fileutils.cpp
psp-g++ -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o /home/batman/Projects/PSP/psplib/pspapplication.o /home/batman/Projects/PSP/psplib/pspapplication.cpp
psp-g++ -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -fno-exceptions -fno-rtti -D_PSP_FW_VERSION=150   -c -o /home/batman/Projects/PSP/psplib/pspcrt.o /home/batman/Projects/PSP/psplib/pspcrt.cpp
psp-gcc -I/home/batman/Projects/PSP/library -I/home/batman/Projects/PSP/psplib -I/home/batman/Projects/PSP/danzeff -I. -I/usr/local/pspdev/psp/sdk/include -O3 -G0 -Wall -g -D_PSP_FW_VERSION=150  -L. -L/usr/local/pspdev/psp/sdk/lib   main.o /home/batman/Projects/PSP/library/utils.o /home/batman/Projects/PSP/library/fileutils.o /home/batman/Projects/PSP/psplib/pspapplication.o /home/batman/Projects/PSP/psplib/pspcrt.o -lpsppower -lpsprtc -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -o empty.elf
main.o&#58; In function `main'&#58;
/home/batman/Projects/PSP/Empty_Text/main.cpp&#58;30&#58; undefined reference to `realpath&#40;char const*, char*&#41;'
collect2&#58; ld returned 1 exit status
make&#58; *** &#91;empty.elf&#93; Error 1
Process terminated with status 2 &#40;0 minutes, 1 seconds&#41;
1 errors, 0 warnings
and this is the makefile

Code: Select all

TARGET = empty
DESCRIPTION = Sony PSP Text Example

INCDIR = $&#40;COMMON_LIBRARY&#41; $&#40;PSP_LIBRARY&#41; $&#40;DANZEFF_LIBRARY&#41;

OBJS_MAIN = main.o

## base library functions, not PSP-specific, add lines in the form OBJS_COMMON += $&#40;COMMON_LIBRARY&#41;/<filename.o>
OBJS_COMMON =
OBJS_COMMON += $&#40;COMMON_LIBRARY&#41;/utils.o
OBJS_COMMON += $&#40;COMMON_LIBRARY&#41;/fileutils.o

## PSP-specific library functions, add lines in the form OBJS_PSP += $&#40;PSP_LIBRARY&#41;/<filename.o>
OBJS_PSP =
OBJS_PSP += $&#40;PSP_LIBRARY&#41;/pspapplication.o
OBJS_PSP += $&#40;PSP_LIBRARY&#41;/pspcrt.o

## PSP-specific, DanZeff on-screen keyboard, enable the line OBJS_DANZEFF += $&#40;DANZEFF_LIBRARY&#41;/<danzeff.o>
OBJS_DANZEFF =
##OBJS_DANZEFF = $&#40;DANZEFF_LIBRARY&#41;/danzeff.o

OBJS = $&#40;OBJS_MAIN&#41; $&#40;OBJS_COMMON&#41; $&#40;OBJS_PSP&#41; $&#40;OBJS_DANZEFF&#41;

CFLAGS = -O3 -G0 -Wall -g
##CXXFLAGS and ASFLAGS are automatically added the CFLAGS in the final &#40;build.mak&#41; make file, so no need to add them here
CXXFLAGS = -fno-exceptions -fno-rtti
ASFLAGS =
LDFLAGS =

##MAKE_PRX = 1
##USE_PSPSDK_LIBC = 1
##USE_KERNEL_LIBC = 1

LIBS = -lpsppower -lpsprtc

EXTRA_TARGETS = EBOOT.PBP
## The title in the XMB
PSP_EBOOT_TITLE = $&#40;DESCRIPTION&#41;
## The icon of the program, png format, 144x80 MAX
##PSP_EBOOT_ICON = $&#40;TARGET&#41;.png
## The background image of the program in the XMB, png format, 480x272 MAX
##PSP_EBOOT_PIC1 = $&#40;TARGET&#41;-pic.png
## The sound being played in the XMB, Atrac3 format
##PSP_EBOOT_SND0  = $&#40;TARGET&#41;.at3

PSPSDK = $&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
##include $&#40;PSPSDK&#41;/lib/build_prx.mak

Hope you can find something.

Thanks for helping,
A.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Oh, you said C, not C++.
Wrap the prototype:

Code: Select all

extern "C" &#123;
  char *realpath&#40;const char *path, char *resolved_path&#41;;
&#125;
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

jimparis wrote:Oh, you said C, not C++.
Wrap the prototype:

Code: Select all

extern "C" &#123;
  char *realpath&#40;const char *path, char *resolved_path&#41;;
&#125;
ehm... it works. :-D

Thank you... gonna save tip this for future issues.
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

realpath

Post by Alberto »

ok, as I said, it works... but...

is it correct, that if I try to explode a path that doesn't exist, it returns NULL?
I see in the man pages that it's buggy, so does this behavior fall into the word "buggy"?
If it _is_ so, I think I'll stuck with my implementation; maybe extend it a little to comply properly with chdir, and that's it. ;-)

Anyway, thanks again for getting it to compile and link.


Cheers, A.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Yes, it needs to exist -- just like any implementation of realpath. I don't know what you mean by "buggy", but returning NULL and errno=ENOENT, ENOTDIR, etc is normal behavior when files or dirs don't exist.

If that's not what you want, you can try using the low-level and nonstandard __psp_path_absolute function from newlib.

Code: Select all

int __psp_path_absolute&#40;const char *in, char *out, int len&#41;;
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

Hi,

sorry, I meant "broken by desing"... but haven't read to the end the manpage. It's "broken" for it's impossible to determine a suitable size for the output buffer, not for the behavior.

TTYTT, I can write C ot C++ code -more or less- easily; what I don't know is the complete library functions... I'm still at the beginning :-(
Most of the times I search the man pages and succeed in finding suitable things; but this time had no clue of realpath (and anyway I would have still hit the missing export thing...)

So I don't discuss what the function does or does not, but it doesn't do what I was expecting it to. I come mainly from Borland's Pascal and Delphi (on Windows envs.), and there, the functions FExpand and ExpandFilePath do exactly what I want: just resolve the "." and "..", shrink any non-leading "//", and add the cwd in front of paths not beginning with the drive; no matter whether the path actually exists or not.

Nevermind, if you like I can post my implementation, you can have a look at it, and just say what is good and what not... that could be of great help for me ;-)

Cheers, A.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Alberto wrote:sorry, I meant "broken by desing"... but haven't read to the end the manpage. It's "broken" for it's impossible to determine a suitable size for the output buffer, not for the behavior.
The size is PATH_MAX. On PSP PATH_MAX is a defined constant, so none of the issues listed in the Linux man page apply.
TTYTT, I can write C ot C++ code -more or less- easily; what I don't know is the complete library functions... I'm still at the beginning :-(
Most of the times I search the man pages and succeed in finding suitable things; but this time had no clue of realpath (and anyway I would have still hit the missing export thing...)
Looking through the newlib source is helpful, that's where all the libc stuff is done and these sort of functions is defined (download newlib and apply psptoolchain/patches/newlib-1.16.0-PSP.patch, then look in newlib/libc/sys/psp)
So I don't discuss what the function does or does not, but it doesn't do what I was expecting it to. I come mainly from Borland's Pascal and Delphi (on Windows envs.), and there, the functions FExpand and ExpandFilePath do exactly what I want: just resolve the "." and "..", shrink any non-leading "//", and add the cwd in front of paths not beginning with the drive; no matter whether the path actually exists or not.
That's what __psp_path_absolute does.
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

jimparis wrote: That's what __psp_path_absolute does.
mmm, ok, it does to some extent... I checked it out, but found the following misbehaviors:
assumed: we run from "host0:/TEST/"

locals...
1. "test.txt" gives "host0:/TEST/test.txt" CORRECT
2. "./test.txt" gives "host0:/TEST/host0:./test.txt" WRONGGG!
3. "host0:test.txt" gives "host0:/TEST/host0:test.txt" WRONGGG!
4. "host0:/test.txt" gives "host0:/test.txt' CORRECT

others...
1. expanding "ms0:test.txt" gives "host0:/TEST/ms0:test.txt" WRONG!
2. expanding "ms0:../test.txt" gives "host0:/TEST/ms0:../test.txt" WRONG!
they should both return, at least, ms0:/test.txt
3. expanding "ms0:/test.txt" gives "ms0:/test.txt" CORRECT
3. expanding "ms0:/../test.txt" gives "ms0:/test.txt" CORRECT

so, even forgetting for a moment the relative paths on different devices (on which I am still working, so no matter for now), what can you tell me now? ;-)


Cheers, A.
carl0sgs
Posts: 33
Joined: Thu Dec 10, 2009 3:51 am
Contact:

Post by carl0sgs »

I don't see why can't you use getcwd.
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

carl0sgs wrote:I don't see why can't you use getcwd.
I do use it.

The thing is that I _want_ to expand relative paths (including . and ..) to absolute ones, no matter whther they exist or not.

So far, realpath doesn't suit my needs, as it returns NULL for non existen paths.

__psp_path_absolute returns wrong resuls, not only on different devices, but on local (getcwd'd) ones too.
see: ./test.txt MUST return host0:/TEST/test.txt (assumed getcwd is host0:/TEST), instead it returns host0:/TEST/host0:./test.txt

Am I stupid or what? ;-)

Cheers, A.

edit: by the way, looking at the source code of __psp_path_absolute I see I had the same approach (the code looks amazingly the same... wow), thou' I caerd for something more about assuming the path is absolute because it begins with a device name, and I also remove trailing /. and /.., that is, not assuming . and .. always end with a /

Again, cheers, A.

P.S.
too lazy to change my profile, but it should now read Location: Sofia
edit: ...ehm, also done that.
carl0sgs
Posts: 33
Joined: Thu Dec 10, 2009 3:51 am
Contact:

Post by carl0sgs »

Alberto wrote:Am I stupid or what? ;-).
Of course not!
It was just that I had posted about getcwd here twice, and didn't got an answer xD

good luck
Alberto
Posts: 51
Joined: Mon Feb 12, 2007 8:16 pm
Location: Sofia

Post by Alberto »

Hi there,
carl0sgs wrote: Of course not!
well, thanks for trusting... :-D

It was just that I had posted about getcwd here twice, and didn't got an answer xD

yeah, I see, but getcwd is one thing, but expanding a relative path prepending the getcwd result and then resolving all the . and .. entries is another.
carl0sgs wrote:good luck
Thanks, I'm almost done, for what are my needs ATM.

P.S.
how's it going on your multitasking thing? Looks amazing. There is also another big project, very similar: NanoDesktop, but as far as I can see your one looks nicer (althou' I would change a bit the graphics, but this is no issue), and faster. Keep the good work up.


Cheers, A.
Post Reply