Welcome! Log In Create A New Profile

Advanced

Directory reading

Posted by g_man 
Directory reading
July 16, 2009 06:29AM
Hello Everyone,

I cannot figure out how to get the file/directory names of the current working directory(like the ls command in linux, or dir in windows). I have already searched google, and read through the sources of a couple programs, but it is hard to understand. So, can anyone help me.
any help is apprecated
thanks
Re: Directory reading
July 16, 2009 07:01AM
Here's an example. It's commented to try to explain it..

//add <> to the outsides of the include files (stupid Phorum)
#include stdio.h
#include sys/types.h
#include dirent.h

int main (argc, **argv){
	if(argc != 2){								//make sure they used the program correctly
		printf("Usage: %s directory",argv[0]);
	}
	DIR *dp;											//directory pointer
	struct dirent *ep;									//directory entities

	dp = opendir (argv[1]);					//opens the directory given as an argument from the command line
	if (dp != NULL){						//makes sure the directory could be opened
		while(ep = readdir (dp)){			//while there is a file/directory
			puts(ep->d_name);				//puts (prints a string + \n). ep->d_name is the name of the file/directory
		}
		closedir (dp);		//closes the directory after reading from it
	}
	return 0;			//return success
}



Edited 1 time(s). Last edit at 07/16/2009 07:03AM by jsmaster.
Re: Directory reading
July 16, 2009 07:24AM
Looks good i'll try it when i can

EDIT: I tried it and it worked :)
I hope i can get the rest working.
thanks

EDIT2: Ok I have a problem, which i belive to be caused by this line

if((ep->d_name == "boot.dol") || (ep->d_name == "boot.elf"))
gcc gives me a warning
warning: comparison with string literal results in unspecified behaviour

My code runs and i can get to my ending loop, but it doesn't do what it is supposed to. I want it to print the folder names of every folder in apps with boot.dol or boot.elf
Here is the code that is supposed to print the folder names
for(i=1;i<=dircounter;i++){
		if(hasdol == 1){ // If the foler has a dol
			puts(appnames); //print the app name
		}	
	}



Edited 2 time(s). Last edit at 07/16/2009 08:47PM by g_man.
Re: Directory reading
July 16, 2009 09:46PM
Quote
g_man
EDIT2: Ok I have a problem, which i belive to be caused by this line

if((ep->d_name == "boot.dol") || (ep->d_name == "boot.elf"))
gcc gives me a warning
warning: comparison with string literal results in unspecified behaviour
Well you can't just compare two string literals that way (or yes you can, but you can't know what it does as the warning says). You should use strcmp() from "string.h" (or from "cstring" for c++) header.
Read this for more information.
Re: Directory reading
July 17, 2009 06:20AM
Ok, this should hopefully be my last error. When i try to save the names of the directories, it doesn't work.
AKA what is wrong with this statement
appnames[dircounter] = (ep->d_name);
This code right before it works
puts(ep->d_name);
thanks
Re: Directory reading
July 17, 2009 12:04PM
Quote
g_man
Ok, this should hopefully be my last error. When i try to save the names of the directories, it doesn't work.
AKA what is wrong with this statement
appnames[dircounter] = (ep->d_name);
This code right before it works
puts(ep->d_name);
thanks
You now only store the char-pointer, not the actual string. Maybe you would like use strcopy to copy the actual name.
I think the problem is that string that d_name points to gets deallocated before you use your copy of pointer, but I'm not entirely sure about this.
Re: Directory reading
July 17, 2009 07:53PM
Ok, using strcpy gave me a stack dump, I used this code
strcpy(appnames[dircounter],(ep->d_name));
I also tried memcpy, and it did the same thing
memcpy((void*)appnames[dircounter],(void*)(ep->d_name),strlen((ep->d_name))+1);
Re: Directory reading
July 17, 2009 10:36PM
Is appnames a char* or char**? Maybe include your entire source file so we can see exactly what you are doing.
Re: Directory reading
July 18, 2009 01:03AM
Here you go:
#include stdio.h> //<
#include stdlib.h>
#include gccore.h>
#include wiiuse/wpad.h>
#include fat.h>
#include unistd.h>
#include sys/types.h>
#include dirent.h>
#include string.h>


static void *xfb = NULL;
static GXRModeObj *rmode = NULL;

//Global variables
FILE *fileptr = NULL;
char path[30];

//Prints a message then quits
void die(char *msg) {
	printf(msg);
	printf("\nQuiting in 10 seconds\n");
	sleep(10);
	printf("Goodbye");
	exit(0);
}	

//Checks if you can open root of SD
int canOpenRoot(){
	DIR_ITER *root=diropen("SD:/");
	//If root opened(not NULL) close root and return 1
	if(root){
		dirclose(root);
		return 1;
	}
	//Else return failure
	return 0;
}	

//Initialize FAT
void init_FAT(){
	//If fatInitDefault returns 0, quit
	if(!fatInitDefault()){
		die("There was an error initializing fat, sorry");
	}	
	
	/*if(!canOpenRoot()); {
		die("The root of the SD cannot be opened, sorry");
	}

	if(chdir("SD:/") == -1); {
		die("Cannot change working directory, sorry");
	}*/
}	

//Initialize's everyting :)
void initialize() {

	VIDEO_Init();
	WPAD_Init();
	rmode = VIDEO_GetPreferredMode(NULL);
	xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
	console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
	VIDEO_Configure(rmode);
	VIDEO_SetNextFramebuffer(xfb);
	VIDEO_SetBlack(FALSE);
	VIDEO_Flush();
	VIDEO_WaitVSync();
	if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
	
	printf("\x1b[2;0H");
	init_FAT();

}


//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------

	
	initialize();
	puts("1");
	sleep(1);
	
	//Variables
	int dircounter = 0;
	int hasdol[50]; //Store information weather each file has a boot.dol, or boot.elf
	hasdol[0] = 0;
	char *appnames[50];
	appnames[0] = NULL; //So I don't have to bother with 0
	
	char appdir[] = "SD:/apps/";	
	puts("2");
	sleep(1);
	
	DIR *dp;
	struct dirent *ep;
	if(opendir("SD:/apps")){ //If apps exists
		dp = opendir("SD:/apps");
		while((ep = readdir(dp))){
			puts(ep->d_name);
			dircounter++; //counts number of files
			//appnames[dircounter] = (ep->d_name);
			//strcpy(appnames[dircounter],(ep->d_name)); // Saves the name of each directory
			//memcpy((void*)appnames[dircounter],(void*)(ep->d_name),strlen((ep->d_name))+1);
			
		}
		closedir(dp);
	} else { // If the was no apps directory try to create it
		printf("the folder apps doesn't exist, creating it...");
		opendir("SD:/");
		if(mkdir("apps", 0777) == -1){ // If cannot create apps form root, quit
			die("There was an error creating the apps file\nTry creating it on your computer");
		}
	}
	puts("3");
	sleep(1);
	int i;
	for(i = 1;i<=dircounter;i++){ //For each folder...
		strcpy(path, appdir); //Copy SD:/apps to path
		strcat(path,appnames); //add the app name to the end of path
		if(opendir(path)){ //If the folder exists
			dp = opendir(path);
			while((ep = readdir(dp))){
				//puts(ep->d_name);
				//If a file is named boot.dol/boot.elf
				if((strcmp(ep->d_name,"boot.dol")) || (strcmp(ep->d_name,"boot.elf"))){
					hasdol = 1; //Set the the folder has a dol
				}
			}
			
		}
		closedir(dp);
	}
	
	puts("4");
	sleep(1);
	//Prints the names of the folders that have boot.dol/boot.elf
	for(i=3;i<=dircounter;i++){ //skips the . and .. entries
	
		//printf("%d\n",i);
		if(hasdol == 1){ // If the foler has a dol
			printf("%s\n",appnames); //print the app name
		
		}	
	}	
	puts("DONE");
	
	for(i=1;i<=dircounter;i++) {
			printf("%d\n",hasdol);
	}	
	
	printf("%s\n",appnames[5]);
	printf("%s\n",appnames[7]); //Just to test appnames
	
	while(1) {
		//Read controller data
		WPAD_ScanPads();
		u32 pressed = WPAD_ButtonsDown(0);
		if ( pressed & WPAD_BUTTON_HOME ) exit(0);

		

		VIDEO_WaitVSync();
	}

	return 0;
}

I am trying to get the names of every app that has a boot.dol in it. The print there names

EDIT: I put puts("a number") and sleep(1) so i could find my errors



Edited 1 time(s). Last edit at 07/18/2009 01:05AM by g_man.
Re: Directory reading
July 18, 2009 04:11AM
Quote
g_man
Here you go:
	char *appnames[50];
	appnames[0] = NULL; //So I don't have to bother with 0
This won't allocate the memory needed for each char* in that array. First you need to add #include malloc.h> to your includes.
Quote
g_man
Here you go:
	if(opendir("SD:/apps")){ //If apps exists
		dp = opendir("SD:/apps");
		while((ep = readdir(dp))){
			puts(ep->d_name);
			dircounter++; //counts number of files
			//appnames[dircounter] = (ep->d_name);
			//strcpy(appnames[dircounter],(ep->d_name)); // Saves the name of each directory
			//memcpy((void*)appnames[dircounter],(void*)(ep->d_name),strlen((ep->d_name))+1);
			
		}
		closedir(dp);
	}


Then add appnames[dircounter] = (char*)malloc(strlen(ep->d_name)+1); right before either the strcpy or memcpy (both will do same thing, at least in this scenario).



Edited 1 time(s). Last edit at 07/18/2009 04:11AM by jsmaster.
Re: Directory reading
July 18, 2009 05:03AM
OK, I'm getting an stack dump, at this line i belive
if(opendir(path))
I found this out by changing my code to this.
for(i = 3;i<=dircounter;i++){ //For each folder...
		puts("1111111111111");
		sleep(1);
		strcpy(path, appdir); //Copy SD:/apps to path
		puts("2222222222222");
		sleep(1);
		strcat(path,appnames); //add the app name to the end of path
		puts("3333333333333");
		sleep(1);
		if(opendir(path)){ //If the folder exists
			puts("4444444444444444");
			sleep(1);
			dp = opendir(path);
			puts("5555555555555555555");
			sleep(1);
			while((ep = readdir(dp))){
				//puts(ep->d_name);
				//If a file is named boot.dol/boot.elf
				puts("666666666666666666666666666666");
				sleep(1);
				if((strcmp(ep->d_name,"boot.dol")) || (strcmp(ep->d_name,"boot.elf"))){
					puts("77777777777777777777777777777777777777");
					sleep(1);
					hasdol = 1; //Set the the folder has a dol
				}
			}
			
		}
		closedir(dp);
	}
I added lines in for each statement, and it stoped after the third set of pauses.

This has never happened before, and the only changes i made are the ones suggested by jmaster
Re: Directory reading
July 18, 2009 02:29PM
Quote
g_man
...
		strcpy(path, appdir); //Copy SD:/apps to path
		puts("2222222222222");
		sleep(1);
		strcat(path,appnames); //add the app name to the end of path
		puts("3333333333333");
		sleep(1);
		if(opendir(path)){ //If the folder exists
...
path-variable contains full path to application and you're trying to use it as a directory. It's only natural that opendir can't open file as a directory. You should only send appdir to opendir-function, not the whole path.
Re: Directory reading
July 18, 2009 05:37PM
It works now. LOL my error was that i forgot to add
//strcpy(appnames[dircounter],(ep->d_name));
It works now
thanks for helping

EDIT: OK, I'm trying to delete a folder with unlink("folder_name");. I can get it to work when i delete all the files in a folder, then delete the folder, but I don't want to have to do this.
So, is there a way to delete a folder, without deleting all of the files inside of it



Edited 1 time(s). Last edit at 07/19/2009 06:05PM by g_man.
Sorry, only registered users may post in this forum.

Click here to login