Game Development Community

Save/Load - Deleting Files and Folders

by Nicolai Dutka · in Torque Game Engine · 03/04/2008 (9:32 pm) · 20 replies

I have code that makes a folder with the client's name on it and puts 2 '.cs' files in it, then updates a master "saveList.txt". This all works fine and dandy. I have a list in my GUI that updates based on the master list and can be edited "in game" which then reflects changes in the master list.

In other words:
I can add/remove items from my master list.
I can add folders and place files in them.
I CANNOT delete the created folders....

I feel dirty somehow for asking this but I need this functionality.... How can I delete Windows folders using Torque Script in TGE 1.5.2?

EDIT: I guess I should note that I am trying to delete a folder within my project, not directly off the C: drive. :P

#1
03/05/2008 (5:45 am)
Don't feel dirty or bad about asking questions, that's why these forums exist.

Now, I don't think Torque has an out of the box solution for directory deletion (correct me if I'm wrong, please).

However, I have written C++ code to do so in the past:

if( rmdir("C:/Torque/Test") != 0 )
{
   printf("Error error error");
}

So, if I were coding the app, I would do the following:

1. Open engine\console\ConsoleFunctions.cc
2. Find this line of code:
ConsoleFunctionGroupBegin( FileSystem, "Functions allowing you to search for files, read them, write them, and access their properties.");
(you'll want to write your new code in this area for the sake of organization)
3. Create a function that deletes all the files in the directory and sub-directories. Then, at the end, call rmdir
4. Finally, create a ConsoleFunction that calls the method you just created

Does that make sense?
#2
03/05/2008 (7:10 am)
Yes, makes sense, but my C++ skills are a bit sketchy... my skills in Torque Script are more than adequate, I just don't have any experience at all making C++ talk to Torque and I have a limited time to get this working.

If anyone has another idea, I'd love to hear it. Otherwise, I will look into making the necessary engine code to make this work...
#3
03/05/2008 (8:01 am)
I did manage to find a way to delete files, but it won't let me delete entire folders.

fileDelete("pathname/filename.cs");

I tried some funky stuff with of course and got no results:

fileDelete(fileBase("path"));  //does nothing
fileDelete("path");  //does nothing
fileBase("path").delete(); //obviously, this object does not exist

I am looking at the C++ code now and let me tell you, it is a world of difference from Torque Script.

I found 2-3 console functions which I think will come in handy for helping me:

Get base path (this is what I am wanting to delete)
ConsoleFunction(fileBase, const char *, 2, 2, "fileBase(fileName)")
{
   argc;
   const char *path = dStrrchr(argv[1], '/');
   if(!path)
      path = argv[1];
   else
      path++;
   char *ret = Con::getReturnBuffer(dStrlen(path) + 1);
   dStrcpy(ret, path);
   char *ext = dStrrchr(ret, '.');
   if(ext)
      *ext = 0;
   return ret;
}

This might be another way to get what I am wanting to delete
ConsoleFunction(getWorkingDirectory, const char *, 1, 1, "getWorkingDirectory()")
{
   return Platform::getWorkingDirectory();
}

Delete Files
ConsoleFunction(fileDelete, bool, 2,2, "fileDelete('path')")
{
   static char fileName[1024];
   static char sandboxFileName[1024];

   Con::expandScriptFilename( fileName, sizeof( fileName ), argv[1] );
   dSprintf( sandboxFileName, 1024, "%s/%s", Platform::getWorkingDirectory(), fileName );
   
   return dFileDelete(sandboxFileName);
}


My theoretical code based on that
ConsoleFunction(folderDelete, bool, 2,2, "folderDelete('path')")
{
   return dFolderDelete(getWorkingDirectory());
}
#4
03/05/2008 (8:39 am)
Do you mind if you get Windows specific code? Not sure if you care about being cross-platform or not. If not, then I have your code solution if you want it.
#5
03/05/2008 (8:52 am)
dFolderDelete(getWorkingDirectory());
Doesn't this seem kind of dangerous? Wouldn't this only be useful with a folder path as parameter and internal access to the sandbox location and checks to make sure that the location really is under the sandbox?

Will your routines work with non-English characters in the file paths? (People's names, foreign translations of "program files", spaces, etc.)

Frankly, my only real suggestion is to redesign the system to get rid of the requirement for folder deletion, using differentiated file names to keep the two files together. Folder deletion systems with any real power are dangerous. (What's this character name "..\..\..\.."? My stupid little brother must have been playing with my system again. I'll just delete it.)
#6
03/05/2008 (8:54 am)
Windows specific is fine. This is going to be a Windows only program.
#7
03/05/2008 (9:14 am)
Well, first and foremost, you want to delete all the files in the folder:

Copy this script function to your mod:
function deleteDirectory(%path)
{
   echo("Deleting " @ %path);
   
   %file = "";
   %file = findFirstFile(%path @ "/*.*");
   
   while(%file !$= "")
   {
      fileDelete(%file);
      %file = "";
      %file = findNextFile(%path @ "/*.*");
   }
}

That should delete all the files in that directory. I'll modify this post after lunch to show you how to delete the actual folder, if you wish.
#8
03/05/2008 (9:15 am)
Yes please!

I did know about emptying the folder first and have no problems there. :P
#9
03/05/2008 (9:30 am)
In engine\console\consoleFunctions.cc
ConsoleFunction(folderDelete, bool, 2,2, "folderDelete('path')")
{
	return dFolderDelete(argv[1]);
}

In engine\platform\platform.h:

Find this code:
extern bool dFileDelete(const char *name);

And put the following below it:
extern bool dFolderDelete(const char *name);


In engine\platformWin32\winFileio.cc:

Add this function below dFileDelete():
bool dFolderDelete(const char* name)
{
	if(!name || (dStrlen(name) >= MAX_PATH))
		return false;

	int result = _rmdir(name);

	return result;
}

*NOTE* - Not finished yet. Still need to test, fix syntax, etc.
#10
03/05/2008 (9:34 am)
Ok, I just ran the code. Works like a charm for me in release. Gonna try debug now.

*BIG NOTE* - I HEREBY ABSOLVE MYSELF OF WHATEVER YOU DO WITH THIS CODE.

I just tried running some odd scenarios to get a crash.

I passed "starter.fps/data" as my directory to delete.

Every single file in all the sub-folders of the data directory was deleted, but not the folders themselves.

This is an obviously nasty piece of code that should have paranoid error checking EVERY WHERE.

If you are going to delete an entire directory, make sure it is a leaf directory, or you use a different manner of emptying the files in that directory alone. Otherwise, my script functionality to delete the files is going to ruin your day.
#11
03/05/2008 (11:04 am)
Sorry, I just couldn't resist.

img.photobucket.com/albums/v217/slymarbo/bigws0.jpg
It is a considerably powerful bit of code though, and it was fun watching the data directory get deleted. How about later we try deleting the example folder? ;)
#12
03/05/2008 (12:43 pm)
Anyone who thinks they would never make a mistake with recursive directory deletion, well, an old yachting saying applies:

If yee aint been a'ground, yee aint sail't much, ayah.

These things can be like mini black holes. If you drop it, you will be lucky to stop it before it eats its way to the center of the Earth.
#13
03/05/2008 (12:54 pm)
Error:

..\engine\platformWin32\winFileio.cc(1183) : error C3861: '_rmdir': identifier not found



I am using a clean install of TGE 1.5.2
#14
03/05/2008 (1:20 pm)
If you google for _rmdir
msdn2.microsoft.com/en-us/library/wt8es881(VS.80).aspx

You find it needs
#include
#15
03/05/2008 (1:28 pm)
@Matthew - Thanks, forgot to add that part.

Yeah, you want to include direct.h, here is where I put mine:

Open engine\platformWin32.h

Find this code section:
#include <windows.h>

#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif

And replace it with this:
#include <windows.h>
[b]#include <direct.h>[/b]
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#16
03/05/2008 (1:31 pm)
Oh, I already figured that part out. :P I am not a complete C++ n00b :P

THANKS A TON!!

I hope this helps others out too! (Hopefully it doesn't help a poor n00b in wiping out his/her hard drive....)

To: Scott Burns
Thanks for that post! Can I use that picture?
#17
03/05/2008 (2:35 pm)
Ok, you might have guessed this was going to come up:

How do I check for specific characters in a string? I don't want people using file names that could cause problems, so no ., /, #, ^, etc...

PS: Keep in mind some people might try things like:

L33t Sp3ak3r
#337 $p34|{3r

(I think spaces are actually ok)
#18
03/07/2008 (5:26 am)
The pic isn't mine, just one I found with a Google image search. As a side note, some really odd stuff comes up when searching for "with great power comes great responsibility".
#19
03/07/2008 (6:16 am)
First off, if someone tries to talk like that in your game..you should ban them and write code to erase their hard drive....

Kidding...

Umm, the question of delimiters is actually unrelated to my code. Have you searched the forums for string manipulation in Torque? Search for the following keywords:

"string delimiters"
"string manipulation"

Stuff like that.
#20
03/07/2008 (10:33 am)
Ok cool. Thanks a lot for the help!

(There are a couple kids that talk like that in my class. What's worse is, they actually talk like that in real life with their voices too!!! UGH!!!)