Click here to go to the forum index Click here for the home page
 
Author Message

<  TAP and patch development  ~  HDD Directory API

Page 1 of 1
GazzaGuru
Posted: Sat Jun 18, 2005 1:25 pm Reply with quote
Joined: 11 May 2005 Posts: 3
Is it just me or is the HDD API for directory handling rather weak.

It would be nice to be able to get hold of the current working directory, set the current directory from the root and specify directories as a path.
View user's profile Send private message
kidhazy
Posted: Wed Sep 14, 2005 2:00 am Reply with quote
Frequent contributor Joined: 29 May 2005 Posts: 372 Location: Melbourne, Australia
Did anyone ever come up with a working solution for finding the current directory?

I need to know my starting directory so that I can jump into the "UK TAP Project" subdirectory, but be able to jump into other directories (eg. \Data Files) and then come back to where I started from.

_________________
Thanks,
kidhazy.
View user's profile Send private message
DX
Posted: Mon Sep 19, 2005 1:54 am Reply with quote
Frequent contributor Joined: 06 Apr 2005 Posts: 2694
Have you found a solution yet?

If not let me know - I think I can see how it can be done.
View user's profile Send private message
BobD
Posted: Mon Sep 19, 2005 8:09 am Reply with quote
MyStuff Team Joined: 03 Aug 2005 Posts: 4218
Only way I found is to look for eg DataFiles in the current dir, if you cant find it then go up one, and retry, Repeat until you find it, and then you must be in the root. I could never get ChangeDir("/") (or "\\") to work.
View user's profile Send private message Visit poster's website
DX
Posted: Mon Sep 19, 2005 9:43 am Reply with quote
Frequent contributor Joined: 06 Apr 2005 Posts: 2694
The following code finds the current directory, at least on the latest UK firmware beta 5.12.04. It matches '.' with an entry in the parent directory to find the name, repeat till root.

Error handling could be better. e.g. Running out of heap will leave you in the wrong directory.




bool CurrentDirStartCluster (dword* cluster)
{
TYPE_File file;

// '.' should be the first entry, so find it
memset (&file, 0, sizeof (file));
if (TAP_Hdd_FindFirst (&file))
{
while (strcmp (file.name, ".") && TAP_Hdd_FindNext (&file)) {};
}

// return starting cluster of this directory
*cluster = file.startCluster;

return (strcmp (file.name, ".") == 0);
}

char* GetCurrentDirectory (void)
{
dword cluster;
char* path;

path = TAP_MemAlloc (2);

if (path == NULL) return NULL;

strcpy (path, "");

// while we have a '.' entry we work up the tree matching starting clusters
while (CurrentDirStartCluster (&cluster))
{
TYPE_File file;
// move into parent directory and look for a starting cluster match
TAP_Hdd_ChangeDir ("..");
memset (&file, 0, sizeof (file));
if (TAP_Hdd_FindFirst (&file))
{
while ((cluster != file.startCluster) && TAP_Hdd_FindNext (&file)) {};
}
// if we have a match prepend it to the path
if (cluster == file.startCluster)
{
char* temp;

temp = TAP_MemAlloc (strlen (path) + strlen (file.name) + 2);

if (temp == NULL) return NULL;

strcpy (temp, "/");
strcat (temp, file.name);
strcat (temp, path);
TAP_MemFree (path);
path = temp;
}
}

if (strlen (path) == 0) strcpy (path, "/");

// finally we put ourselves back in our starting directory
TAP_Hdd_ChangeDir (path);

return (path);
}
View user's profile Send private message
DB1
Posted: Mon Sep 19, 2005 11:06 am Reply with quote
Frequent contributor Joined: 30 Mar 2005 Posts: 728 Location: Orpington
Nice piece of lateral thinking Smile
View user's profile Send private message
deangelj
Posted: Mon Sep 19, 2005 11:01 pm Reply with quote
Frequent contributor Joined: 29 Mar 2005 Posts: 316 Location: Sydney, Australia
Nice work man - I'll use this right away Very Happy

Just a usage note for users of this code - remember to free the memory returned after the call. e.g.

Code:
char *cDir;

cDir = GetCurrentDirectory();

//use cDir

//free memory allocated by GetCurrentDirectory
TAP_MemFree(cDir);

View user's profile Send private message
simonc
Posted: Sun Sep 25, 2005 12:00 am Reply with quote
Frequent contributor Joined: 12 Apr 2005 Posts: 5639 Location: Cheltenham
People tend to forget rules like 'you must free this memory'. Since the Toppy has a maximum filename length, why not require callers to pass a pointer to buffer of a specific length, or even better, pass 2 parameters, first for the buffer, second for the buffer length.

BTW, does calling this function cause any hard disk thrashing, particularly if the directories being traversed contain lots of files? I'm thinking of mp3 directories in particular.
View user's profile Send private message Visit poster's website
deangelj
Posted: Sun Sep 25, 2005 6:58 am Reply with quote
Frequent contributor Joined: 29 Mar 2005 Posts: 316 Location: Sydney, Australia
DX wrote:
The following code finds the current directory, at least on the latest UK firmware beta 5.12.04. It matches '.' with an entry in the parent directory to find the name, repeat till root.

[code deleted...]

// finally we put ourselves back in our starting directory
TAP_Hdd_ChangeDir (path);

return (path);
}

TAP_Hdd_ChangDir(path); this statement only works with relative paths so because this function gives you a full path, this statement doesn't return you to the original directory.

cheers,
john
View user's profile Send private message
DX
Posted: Sun Sep 25, 2005 7:14 pm Reply with quote
Frequent contributor Joined: 06 Apr 2005 Posts: 2694
deangelj wrote:
DX wrote:
The following code finds the current directory, at least on the latest UK firmware beta 5.12.04. It matches '.' with an entry in the parent directory to find the name, repeat till root.

[code deleted...]

// finally we put ourselves back in our starting directory
TAP_Hdd_ChangeDir (path);

return (path);
}

TAP_Hdd_ChangDir(path); this statement only works with relative paths so because this function gives you a full path, this statement doesn't return you to the original directory.

cheers,
john


It seems to work OK on current UK beta firmware 5.12.04, which is the only one I've tried it on. Are you running on some other firmware version? Would doing TAP_Hdd_ChangDir(&path[1]); work better for other firmwares then?

Edit: I probably should say how I tested the function, in case that has any impact. My test tap ran in application mode, and after getting the current directory it opened a file and wrote the path to it. That file appeared in the same directory as the tap was run from.

Edit: Modified version that uses relative path (it also handles errors a bit better). Is this OK on your firmware?

bool CurrentDirStartCluster (dword* cluster)
{
TYPE_File file;

// '.' should be the first entry, so find it
memset (&file, 0, sizeof (file));
if (TAP_Hdd_FindFirst (&file))
{
while (strcmp (file.name, ".") && TAP_Hdd_FindNext (&file)) {};
}

// return starting cluster of this directory
*cluster = file.startCluster;

return (strcmp (file.name, ".") == 0);
}

char* GetCurrentDirectory (void)
{
dword cluster;
char* path;

path = TAP_MemAlloc (2);

if (path == NULL) return NULL;

strcpy (path, "");

// while we have a '.' entry we work up the tree matching starting clusters
while (CurrentDirStartCluster (&cluster))
{
TYPE_File file;
// move into parent directory and look for a starting cluster match
TAP_Hdd_ChangeDir ("..");
memset (&file, 0, sizeof (file));
if (TAP_Hdd_FindFirst (&file))
{
while ((cluster != file.startCluster) && TAP_Hdd_FindNext (&file)) {};
}
// if we have a match prepend it to the path
if (cluster == file.startCluster)
{
char* temp;

temp = TAP_MemAlloc (strlen (path) + strlen (file.name) + 2);

// no memory - back to starting directory and return NULL
if (temp == NULL)
{
TAP_Hdd_ChangeDir (file.name);
if (strlen (path)) TAP_Hdd_ChangeDir (&path[1]);
TAP_MemFree (path);
return NULL;
}

strcpy (temp, "/");
strcat (temp, file.name);
strcat (temp, path);
TAP_MemFree (path);
path = temp;
}
else
{
// directory structure inconsistent, shouldn't get here
// problem - we can't get back to our starting directory
TAP_MemFree (path);
return NULL;
}
}

if (strlen (path))
{
// finally we put ourselves back in our starting directory
TAP_Hdd_ChangeDir (&path[1]);
}
else
{
// We're at the root
strcpy (path, "/");
}

return (path);
}


Last edited by DX on Sun Sep 25, 2005 11:55 pm; edited 2 times in total
View user's profile Send private message
DX
Posted: Sun Sep 25, 2005 7:42 pm Reply with quote
Frequent contributor Joined: 06 Apr 2005 Posts: 2694
simonc wrote:

People tend to forget rules like 'you must free this memory'. Since the Toppy has a maximum filename length, why not require callers to pass a pointer to buffer of a specific length, or even better, pass 2 parameters, first for the buffer, second for the buffer length.


I've seen the maximum filename length, but that only covers one element in the path. I don't know if the toppy has a maximum pathname length, or maximum depth of directories, it may not. So I rejected a fixed size buffer (on principle I don't like them in api's anyway - they're not future-proof enough).

I wasn't all that keen on the buffer & length approach either. It's just as easy to forget to free buffers you've allocated yourself. And it tends to make the callers coding more complicated, since the caller has to handle the "buffer-too-small" cases.

In any case if someone really wants to it 's easy to put a wrapper round the api to copy the path into user supplied buffers and free the memory.

simonc wrote:

BTW, does calling this function cause any hard disk thrashing, particularly if the directories being traversed contain lots of files? I'm thinking of mp3 directories in particular.


I wouldn't have thought so, but it does rather depend on the efficiency of the toppy directory enumeration functions.
View user's profile Send private message
simonc
Posted: Sun Sep 25, 2005 7:48 pm Reply with quote
Frequent contributor Joined: 12 Apr 2005 Posts: 5639 Location: Cheltenham
Quote:
I've seen the maximum filename length, but that only covers one element in the path.

Good point. My midnight brain didn't consider the fully qualified path length.

On the enumeration front, I did a TAP to do a quick traverse of the mp3 directories to find all .m3u files. With about 10 directories it wasn't exactly speedy (a second or two) or easy on the hard disk (chatter chatter clunk).
View user's profile Send private message Visit poster's website
DX
Posted: Sun Sep 25, 2005 8:22 pm Reply with quote
Frequent contributor Joined: 06 Apr 2005 Posts: 2694
If directory enumeration is slow I guess all we can do is try and work around it by minimising the number of times we call the api's.

Some sort of caching might be possible. If the TAP remembered the starting cluster of the current directory, and the corresponding path, it could quickly check if the current directory had changed the next time it required the info. Of course if the directory structure changed that could confuse it. Maybe if it had an open file the current dirctory to prevent deletion that would work. It's starting to get messy..., I think leave that one till the need is pressing.
View user's profile Send private message
deangelj
Posted: Tue Sep 27, 2005 3:51 am Reply with quote
Frequent contributor Joined: 29 Mar 2005 Posts: 316 Location: Sydney, Australia
DX, thanks for the new version - will test it out.

cheers,
John
View user's profile Send private message
GazzaGuru
Posted: Sat Oct 01, 2005 7:43 pm Reply with quote
Joined: 11 May 2005 Posts: 3
Pretty much what I had to code myself. Though for simple apps a fixed directory structure seems to be more efficient.

Perhaps Topfield could improve their API!
View user's profile Send private message

Display posts from previous:  

All times are GMT + 1 Hour
Page 1 of 1

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum