View unanswered posts | View active topics It is currently Sat May 26, 2018 6:45 pm



Reply to topic  [ 4 posts ] 
 stat() no working properly on another dir than the CWD 
Author Message

Joined: Thu Aug 22, 2013 2:06 pm
Posts: 2
Hello all, I'm working on a simple function that must list the content of any given folder on the card. It seems to be working nice when I list the current directory (".") but whenever I want to explore another folder the function 'stat()' (which seems to be usable according to several examples I came across) gives weird results.

I haven't checked for the time of last access, etc. but as for st_mode and st_size I'm sure there is a problem.
st_mode cannot be exploited to determine whether it's a directory or not with the usual macro S_ISDIR (it always returns 0); however I managed to find the method "elem->d_type == DT_DIR", where elem is the dirent struct, which is working properly.
st_size doesn't give the actual size; in the root (accessed using "/") the size of every item (directories and files) is 34049932, and on some others it comes to 0.

As said above, when I stat in the current working directory, S_ISDIR works fine and the given size is correct.

Here is my code if it can help:
Code:
    struct dirent *elem;
    struct stat st;
   
    const char *dirName = luaL_checkstring(L, 1);        // luaL_checkstring() just gives the name of the folder to be listed
   
    DIR *dir = opendir(dirName);
   
    while ((elem = readdir(dir))) {
        lua_pushstring(L, elem->d_name);
        lua_pushboolean(L, elem->d_type == DT_DIR);
        stat(elem->d_name, &st);
        lua_pushnumber(L, st.st_size);
    }


The "lua_XXX" functions are from the Lua's C API; just think of them as simple output (e.g lua_pushstring() would be as printing elem->d_name). The code is of course missing many parts only related to Lua that I removed so it is clearer.

I gladly thank you for any help about this as it is a major bug in my project.


Thu Aug 22, 2013 3:40 pm
Profile
Site Admin

Joined: Tue Aug 09, 2005 3:21 am
Posts: 1236
Location: UK
If you want to use stat on files not in the current working directory you'll need to concatenate dirName & elem->d_name for the stat call. The function should be returning -1 assuming a file of the same name doesn't exist in the current directory.

S_ISDIR used to work, I'll have a look when I get time & see what's happened.

_________________
Help keep devkitPro toolchains free, Donate today

devkitPro IRC support
Personal Blog


Thu Sep 05, 2013 11:11 pm
Profile ICQ WWW

Joined: Thu Feb 03, 2011 10:47 pm
Posts: 210
Well, here is something similar. Make sure you are checking for errors!

Code:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>

int myReaddir(const char *Path) {
  static char   path[PATH_MAX];
  struct dirent *dent;
  struct stat   st;
  DIR           *dp;
  char          *p, *end = path + PATH_MAX - 1;
  size_t        len = strlen(Path);

  if(Path[0] != '/') {
    /* a relative directory */
    if(getcwd(path, sizeof(path)) == NULL) {
      return 1;
    }
  }
  else if(len < PATH_MAX-1) {
    /* an absolute directory */
    strcpy(path, Path);
  }
  else {
    return 1;
  }

  /* this is where we append each entry's name to the path */
  p = path + len;

  /* make sure there's a trailing slash */
  if(p[-1] != '/') {
    if(p < end-1) {
      *p++ = '/';
      *p = 0;
    }
  }

  /* open the directory */
  dp = opendir(Path);
  if(dp == NULL) {
    return 1;
  }

  /* loop through each directory entry */
  while((dent = readdir(dp)) != NULL) {
    /* let's make sure the path + name fit */
    if(p + strlen(dent->d_name) < end) {
      /* append the name to the path */
      strcpy(p, dent->d_name);

      /* stat the path */
      if(stat(path, &st) != 0) {
        /* an error, do what you want */
      }
      else {
        /* everything successful for this entry */
        printf("%s\n", dent->d_name);
        printf("  Directory: %s\n", dent->d_type == DT_DIR ? "true" : "false");
        printf("  Size:      %zu\n", st.st_size);
      }
    }
    else {
      /* this name was too long, do what you want */
    }
  }

  closedir(dp);

  return 0;
}

int main(int argc, char *argv[]) {
  const char *path = argv[1];

  if(path != NULL)
    return myReaddir(path);
  else
    return 1;
}


Probably the reason S_ISDIR wasn't working and everything has the same size is because stat() is failing and st is not modified.


Fri Sep 06, 2013 3:48 pm
Profile

Joined: Thu Aug 22, 2013 2:06 pm
Posts: 2
Whew I couldn't have guessed there were so many things to check and do before listing a folder ^^ Thank you for the code, I will test it and incorporate it as soon as possible.

According to what you said it seems logical that S_ISDIR is working and was failing because stat() couldn't operate properly.


Fri Sep 06, 2013 4:50 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 4 posts ] 

Who is online

Users browsing this forum: No registered users and 1 guest


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 post attachments in this forum

Search for:
Jump to:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.
Get devkitPro at SourceForge.net. Fast, secure and Free Open Source software downloads