paths
paths
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.
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.
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.
Code: Select all
sceIoChdir("ms0:/PSP/GAME/MYSW/");
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.
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.
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.jimparis wrote:Use realpath:Code: Select all
char buf[MAXPATHLEN]; if (realpath("../", buf) != NULL) { printf("the absolute path is %s\n", buf); }
Where is it defined?
Thanks, A.
I think this is what you need:
(not sure of the values 600 & 601)
Hope it is useful
Code: Select all
#include <dirent.h> // for getcwd
char buffer[601];
getcwd(buffer, 600);
Hope it is useful
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...
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?
I repeat, getcwd() works for me.carl0sgs wrote:I think this is what you need:
(not sure of the values 600 & 601)Code: Select all
#include <dirent.h> // for getcwd char buffer[601]; getcwd(buffer, 600);
Hope it is useful
It's in newlib, but I think it's missing from the header file. Just add its prototype:Alberto wrote: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.jimparis wrote:Use realpath:Code: Select all
char buf[MAXPATHLEN]; if (realpath("../", buf) != NULL) { printf("the absolute path is %s\n", buf); }
Where is it defined?
Thanks, A.
Code: Select all
char *realpath(const char *path, char *resolved_path);
sorry to bug, now I do get it compiled, but get "undefined reference to realpath"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(const char *path, char *resolved_path);
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.
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: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
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.
here's the compilation log (hope it's what you asked)
and this is the makefile
Hope you can find something.
Thanks for helping,
A.
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: In function `main':
/home/batman/Projects/PSP/Empty_Text/main.cpp:30: undefined reference to `realpath(char const*, char*)'
collect2: ld returned 1 exit status
make: *** [empty.elf] Error 1
Process terminated with status 2 (0 minutes, 1 seconds)
1 errors, 0 warnings
Code: Select all
TARGET = empty
DESCRIPTION = Sony PSP Text Example
INCDIR = $(COMMON_LIBRARY) $(PSP_LIBRARY) $(DANZEFF_LIBRARY)
OBJS_MAIN = main.o
## base library functions, not PSP-specific, add lines in the form OBJS_COMMON += $(COMMON_LIBRARY)/<filename.o>
OBJS_COMMON =
OBJS_COMMON += $(COMMON_LIBRARY)/utils.o
OBJS_COMMON += $(COMMON_LIBRARY)/fileutils.o
## PSP-specific library functions, add lines in the form OBJS_PSP += $(PSP_LIBRARY)/<filename.o>
OBJS_PSP =
OBJS_PSP += $(PSP_LIBRARY)/pspapplication.o
OBJS_PSP += $(PSP_LIBRARY)/pspcrt.o
## PSP-specific, DanZeff on-screen keyboard, enable the line OBJS_DANZEFF += $(DANZEFF_LIBRARY)/<danzeff.o>
OBJS_DANZEFF =
##OBJS_DANZEFF = $(DANZEFF_LIBRARY)/danzeff.o
OBJS = $(OBJS_MAIN) $(OBJS_COMMON) $(OBJS_PSP) $(OBJS_DANZEFF)
CFLAGS = -O3 -G0 -Wall -g
##CXXFLAGS and ASFLAGS are automatically added the CFLAGS in the final (build.mak) 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 = $(DESCRIPTION)
## The icon of the program, png format, 144x80 MAX
##PSP_EBOOT_ICON = $(TARGET).png
## The background image of the program in the XMB, png format, 480x272 MAX
##PSP_EBOOT_PIC1 = $(TARGET)-pic.png
## The sound being played in the XMB, Atrac3 format
##PSP_EBOOT_SND0 = $(TARGET).at3
PSPSDK = $(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
##include $(PSPSDK)/lib/build_prx.mak
Hope you can find something.
Thanks for helping,
A.
Oh, you said C, not C++.
Wrap the prototype:
Wrap the prototype:
Code: Select all
extern "C" {
char *realpath(const char *path, char *resolved_path);
}
ehm... it works. :-Djimparis wrote:Oh, you said C, not C++.
Wrap the prototype:Code: Select all
extern "C" { char *realpath(const char *path, char *resolved_path); }
Thank you... gonna save tip this for future issues.
realpath
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.
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.
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.
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(const char *in, char *out, int len);
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.
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.
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.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.
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)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...)
That's what __psp_path_absolute does.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.
mmm, ok, it does to some extent... I checked it out, but found the following misbehaviors:jimparis wrote: That's what __psp_path_absolute does.
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.
I do use it.carl0sgs wrote:I don't see why can't you use getcwd.
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.
Hi there,
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.
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.
well, thanks for trusting... :-Dcarl0sgs wrote: Of course not!
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.
Thanks, I'm almost done, for what are my needs ATM.carl0sgs wrote:good luck
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.