Re: readdir() threadsafe?
Posted: Mon Jun 25, 2012 7:16 am
I added a readdir() loop to my test program and the lack of a lock isn't a exactly a bug; it's just dumb on a multitasking system like AmigaOS. It seems that opendir() reads the directory into a buffer and readdir() reads the files from the buffer. That means that the directory or files can be changed or deleted by another application after opendir() is called and readdir() will still show files that have changed or been deleted.chris wrote:That sounds like a bug in newlib.library.
On the other hand, if I compile my test program with clib2 then opendir() and readdir() function like AmigaDOS and the directory is locked and the files are locked/read read as the application requests the next file in an examine loop.
You should be able to compile my test program and see what I mean. Just create a test directory in ram: (with files) and run the test program in a shell (opendir ram:testdir), delete the directory from another shell and then enter Ctrl-E in the shell you ran the program from. You should see a list of files that have been deleted.
Code: Select all
/* Compile: gcc -O2 opendir.c -o OpenDir -Wall -lauto */
#include <signal.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <dirent.h>
#include <strings.h>
#include <string.h>
#define TEMPLATE "DIR/A,DELAY/K/N"
struct RDArgs *argsdata;
DIR *dirt = NULL;
enum
{
O_DIR, O_DELAY, O_MAX
};
static void cleanup();
int main(int argc, char **argv)
{
int32 args[O_MAX] = {0};
int32 time = 0;
int32 delay = 0;
uint32 signals = 0;
struct dirent *entry = NULL;
signal(SIGINT, SIG_IGN);
if (argc == 0)
{
IDOS->PutErrStr("Error: Shell program\n");
return(RETURN_ERROR);
}
argsdata = IDOS->ReadArgs(TEMPLATE, args, NULL);
if (!argsdata)
{
IDOS->PrintFault(IDOS->IoErr(), "Error");
cleanup();
return(RETURN_ERROR);
}
if (args[O_DELAY])
delay = *(int32 *)args[O_DELAY];
if ((delay > 0) && (delay < 300))
time = delay * 50;
if (args[O_DIR])
{
dirt = opendir((char *)args[O_DIR]);
if (!dirt)
{
IDOS->Printf("Directory not found\n");
cleanup();
return(RETURN_ERROR);
}
}
if (time > 0)
{
IDOS->Printf("Opened %s - Waiting %ld Seconds\n", args[O_DIR], delay);
IDOS->Delay(time);
}
else
{
IDOS->Printf("Opened %s - Waiting for Ctrl-E\n", args[O_DIR]);
signals = IExec->Wait(SIGBREAKF_CTRL_E);
}
while ((entry = readdir(dirt)))
{
if ((strcmp(entry->d_name, ".") == 0)||(strcmp(entry->d_name, "..") == 0))
continue;
IDOS->Printf("Filename is %s\n", entry->d_name);
}
cleanup();
return(RETURN_OK);
}
void cleanup(void)
{
if (dirt) closedir(dirt);
if (argsdata) IDOS->FreeArgs(argsdata);
}