FileSystem recursive function generates weird file names

I have an implementation of the File system on OS 4.2.0. During some boots, the struct returned from readdir() gives a file name (d_name) with strange symbols, so the unlink will fail. It works fine on some boots. Has anyone seen something like this before? From what I can tell, I never created a file with this name.

	int RemoveTree(const char* path, uint32_t& iter_guard)
	{
		DIR* dir = opendir(path);
		int returnVal = -1;

		if (dir) {
			struct dirent *dirent;

			returnVal = 0;
			while(!returnVal && (dirent=readdir(dir))) {
				char *tmpbuf;
				size_t length;

				if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
					continue;

				length = strlen(path) + strlen(dirent->d_name) + 2;
				tmpbuf = (char*)malloc(length);

				if (tmpbuf) {
					if (path[strlen(path)-1] == '/')	snprintf(tmpbuf, length, "%s%s", path, dirent->d_name);
					else	snprintf(tmpbuf, length, "%s/%s", path, dirent->d_name);

					switch(dirent->d_type) {
					case DT_DIR:
						if (!returnVal){
							returnVal = RemoveTree(tmpbuf, iter_guard);
							if (returnVal) Serial.println("RemoveTree() - Recursive call failure");
						}
						break;
					default:
						if (!returnVal)
						{ 	
							returnVal = unlink(tmpbuf);
							if(returnVal)
							{
								Serial.println("RemoveTree() - unlink failure");
								Serial.println(tmpbuf);
								Serial.println(dirent->d_name);
							}
						}
						break;
					}
				}
			}
			closedir(dir);
		}

		if (!returnVal)
		{	
			returnVal = rmdir(path);
			if (returnVal)
			{
				Serial.println("RemoveTree() - rmdir failure");
				Serial.println(path);
			}
		}
		return returnVal;
	}

Here's an image of when the unlink fails.

I have a couple theories and will run some tests later today. I'm guessing either you need to use readdir_r because of the way the temporary result is returned from readdir, or you can't continue iteration of a directory after deleting a file from it.

1 Like

I created a library with a number of useful utility functions:

  • Store or read a string in a file
  • Store or read an array of bytes in a file
  • Store or read a struct in a file
  • Store or read a Variant in a file. This can be used for structured data, including JSON (Device OS 5.6.0 and later).
  • Create a directory and parent directories (mkdirs)
  • Delete a directory recursively (deleteRecursive)
  • Measure disk usage of a directory
  • Walk the directory tree and call a callback or lambda for each file or directory
  • Parse a pathname
  • Join pathname components

You can also copy out the parts of the recursive delete function or use it as a model to change how yours works. I'm not completely sure why yours didn't, but this one definitely works.

FileHelperRK library on Github

5 Likes

That's pretty cool! Thanks Rick.

@rickkas7, amazing... as usual!