Date: Fri, 18 Aug 2000 02:04:18 -0400 (EDT) From: "Mark W. Krentel" <krentel@dreamscape.com> To: scott@zorch.sf-bay.org Cc: freebsd-emulation@FreeBSD.ORG, marcel@cup.hp.com Subject: Re: Linuxulator, getdents and Citrix Message-ID: <200008180604.CAA04991@dreamscape.com>
next in thread | raw e-mail | index | archive | help
> As nearly as I can tell, the linux_getdents call is returning a null result
> instead of a correct set of directory entries.
I have also seen a problem with the Linux ls, readdir and getdents
when reading non-ufs partitions. Take a look at PR kern/19407. It
started with a panic when running Linux binaries from an ext2
partition. Bruce Evans found and fixed some buffer overruns in the
ext2fs code. But I must have found two separate problems because I'm
still seeing a problem with readdir.
The remaining problem is that the Linux readdir(3) prematurely returns
NULL on non-ufs partitions, and hence ls outputs too few files. Are
your directories on ext2 or NFS partitions? Does it make a difference
if you move them to a local ufs partition? For me, readdir correctly
reads ufs directories, but fails on ext2 and cdrom. I haven't tried
NFS yet.
I'd be very interested in your results of these experiments. Below
are two simple programs to list a directory, using readdir(3) and
getdents(2). Compile the programs in Linux and run them in the
Linuxulator on various directories. For me, getdents returns the
right answer with any buffer size, but readdir prematurely returns
NULL. I can send you uuencoded binaries, if you don't have access to
a Linux machine.
--Mark
--------------------------------------------
/*
* List directory contents with opendir and readdir.
* Basically the same as "ls -1af".
* Usage: readdir directory
*/
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
void my_err(char *mesg)
{
printf("Error: %s\n", mesg);
exit(1);
}
int main(int argc, char **argv)
{
DIR *dp;
struct dirent *de;
int n;
if (argc < 2) my_err("missing directory");
if ((dp = opendir(argv[1])) == NULL)
my_err("unable to open directory");
n = 0;
while ((de = readdir(dp)) != NULL)
{
printf("%s\n", de->d_name);
n++;
}
printf("Total: %d files\n", n);
return 0;
}
--------------------------------------------
/*
* Print directory contents with getdents.
* Usage: getdents directory [ buffer-size ]
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <linux/unistd.h>
#include <stdio.h>
#define MAX_BUF_SIZE 100000
#define DEF_BUF_SIZE 90000
#define DEF_MAGIC 0x0f
_syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);
void my_err(char *mesg)
{
printf("Error: %s\n", mesg);
exit(1);
}
int main(int argc, char **argv)
{
char area[MAX_BUF_SIZE];
struct {
int inode;
int offset;
short len;
char d_name[4];
} *dep;
int used, size, magic;
int num_calls, num_files;
int max_touch, touch;
int pos, fd, i;
/*
* Open directory and set fd.
*/
if (argc < 2) my_err("missing directory");
if ((fd = open(argv[1], O_RDONLY)) == -1)
my_err("unable to open directory");
/*
* Set buffer size.
*/
if (argc < 3)
size = DEF_BUF_SIZE;
else if (sscanf(argv[2], "%d", &size) != 1)
my_err("unable to scanf buffer size");
if (size > MAX_BUF_SIZE)
my_err("buffer size too large");
/*
* Main loop: call getdents until returns 0.
*/
magic = DEF_MAGIC;
num_calls = 0;
num_files = 0;
max_touch = 0;
for (i = 0; i < MAX_BUF_SIZE; i++) area[i] = magic;
while ((used = getdents(fd, (struct dirent *) area, size)) > 0)
{
num_calls++;
touch = 0;
for (i = size; i < MAX_BUF_SIZE; i++)
{ if (area[i] != magic) touch = i; }
if (touch > max_touch) max_touch = touch;
printf("\nCall: %d Used: %d Size: %d Touch: %d\n",
num_calls, used, size, touch);
pos = 0;
while (pos < used)
{
num_files++;
dep = (void *) (area + pos);
printf("%s ", dep->d_name);
pos += dep->len;
}
printf("\n");
for (i = 0; i < MAX_BUF_SIZE; i++) area[i] = magic;
}
printf("\nCalls: %d Files: %d Touch: %d\n",
num_calls, num_files, max_touch);
return 0;
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-emulation" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008180604.CAA04991>
