SD library question.

Working on file commands and having problems with listing directories.

The first time to list any directory seems fine, if I go back to a directory after listing a different directory files & directory names will be missing.

#include <SD.h>
#include <lists.h>
#include <lilParser.h>

enum commands { noCommand, rm, ls, pwd, cd, mkdir, rmdir };

lilParser mParser;

char workingDir[40] = "/";
char cmdCursor[] = ">";

void setup(void) {

  Serial.begin(9600);
  while (!Serial);
  if (!SD.begin(4)) {
    Serial.println(F("SD Drive failed to boot."));
    Serial.println(F("Shutting down."));
    while(true);
  }
  mParser.addCmd(rm, "rm");
  mParser.addCmd(ls, "ls");
  mParser.addCmd(pwd, "pwd");
  mParser.addCmd(cd, "cd");
  mParser.addCmd(mkdir, "mkdir");
  mParser.addCmd(rmdir, "rmdir");
  Serial.print(cmdCursor);
}


bool removeFile(void) {

    char fileName[20];
    char filePath[40];
    File theFile;
    bool  success;

    success = false;
    if (mParser.numParams()) {
      mParser.getParam(fileName);
      strcpy(filePath,workingDir);
      strcat(filePath,fileName);
      if (SD.exists(filePath)) {
        theFile = SD.open(filePath);
        if (!theFile.isDirectory()) {
          theFile.close();
          success = SD.remove(filePath);
          if (!success) {
            Serial.println(F("Unknown file error."));
          }
        } else {
          theFile.close();
          Serial.print(fileName);Serial.println(F(" is not a file."));
        }
      } else {
        Serial.println(F("No such file name."));
      }
    } else {
      Serial.println(F("Missing file name."));
    }
    return success;
  }


void listDirectory(void) {

    File wd;
    File entry;
  
    wd = SD.open(workingDir);
    do {
      entry = wd.openNextFile();
      if (entry) {
        Serial.print(entry.name());
        if (entry.isDirectory()) {
          Serial.println("/");
        } else {
          Serial.print("\t"); Serial.println(entry.size(), DEC);
        }
      }
    } while (entry);
    wd.rewindDirectory();
    wd.close();
  }


bool changeDirectory() {

    File  testFile;
    bool  success;
    char  path[20];
    char  temp[40];
    byte  trace;
    
    success = false;
    if (mParser.numParams()) {
      mParser.getParam(path);
      if (!strcmp(path,"..")) {
        trace = strlen(workingDir)-2;
        if (trace>0) {
          while(workingDir[trace]!='/' && trace>0) {
            trace--;
          }
          workingDir[trace+1] = '\0';
        } else {
          Serial.println(F("Already at root."));
        }
      } else {
        strcpy(temp, workingDir);
        strcat(temp, path);
        if (SD.exists(temp)) {
          testFile = SD.open(temp);
          success = testFile.isDirectory();
          if (success) {
            strcpy(workingDir, temp);
          } else {
            Serial.println(F("Path must be directory names, not filenames."));
          }
        } else {
          Serial.println(F("No such directory."));
        }
      }
    } else {
      Serial.println(F("Missing directory name."));
    }
    return success;
  }


  bool makeDirectory(void) {
    Serial.println(F("Not yet implemented."));
  }

  bool removeDirectory(void) {
    Serial.println(F("Not yet implemented."));
  }


  void loop() {

    char      inChar;
    commands  command;

    if (Serial.available()) {
      inChar = Serial.read();
      Serial.print(inChar);
      command = mParser.addChar(inChar);
      switch ((int)command) {                       // Cheat: Allows -1 passed back as error.
        case noCommand : break;
        case rm : removeFile(); break;
        case ls : listDirectory(); break;
        case pwd : Serial.print(workingDir);Serial.println("|"); break;
        case cd : changeDirectory(); break;
        case mkdir : makeDirectory(); break;
        case rmdir : removeDirectory(); break;
        case -1 : Serial.println("???"); break;
      }
      if (command) Serial.print(cmdCursor);
    }
  }

If you want to see the rest of the librarys, the parser & lists, just say the word. And I’ll add 'em.

Thanks.

-jim lee

Don't bother, I figured it out.

Thanks!

-jim lee

    if (mParser.numParams()) {

Why would a function called numParams() return a boolean? If it doesn't, why do you treat it as though it does?

     if (!strcmp(path,"..")) {

strcmp() returns -n, 0, or +n, depending on the lexical order of the entries. It would be far more understandable to compare the value to 0.

Where do you rewind to the root directory?

Somewhere in my foggy memory I recall that a boolean defined as 0 or not 0. IE any number not 0 for true & 0 for false. I think I picked it up back when I learned c a long, long time ago. I’ve been using them in that way ever since.

if (mParser.numParams()) { ← if it returns 0 I’m treating it as false. At that point thats all I was looking for. Got any params at all?

if (!strcmp(path,"…")) { ← Again, I never really thought about it. I’d been doing the string checks like that since I learned c.

rewinding the root was 1/2 the problem. I’d assumed going out of scope would call the File’s destructor and that would take care of closing it. But that does not seem to be the case. I had to explicitly close each and every one before it would work corretly.

I’m surprised you didn’t catch my force casting the enum to an int to catch the -1 error flag when parsing. I plan on re-writing that bit.

-jim lee