From owner-freebsd-emulation Thu Aug 17 23: 5:58 2000 Delivered-To: freebsd-emulation@freebsd.org Received: from io.dreamscape.com (io.dreamscape.com [206.64.128.6]) by hub.freebsd.org (Postfix) with ESMTP id 22B5037B724 for ; Thu, 17 Aug 2000 23:05:52 -0700 (PDT) Received: from dreamscape.com (sA15-p48.dreamscape.com [209.217.195.111]) by io.dreamscape.com (8.9.3/8.8.4) with ESMTP id CAA02804; Fri, 18 Aug 2000 02:02:39 -0400 (EDT) X-Dreamscape-Track-A: sA15-p48.dreamscape.com [209.217.195.111] X-Dreamscape-Track-B: Fri, 18 Aug 2000 02:02:39 -0400 (EDT) Received: (from krentel@localhost) by dreamscape.com (8.9.3/8.9.3) id CAA04991; Fri, 18 Aug 2000 02:04:18 -0400 (EDT) (envelope-from krentel) Date: Fri, 18 Aug 2000 02:04:18 -0400 (EDT) From: "Mark W. Krentel" Message-Id: <200008180604.CAA04991@dreamscape.com> To: scott@zorch.sf-bay.org Subject: Re: Linuxulator, getdents and Citrix Cc: freebsd-emulation@FreeBSD.ORG, marcel@cup.hp.com Sender: owner-freebsd-emulation@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org > 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 #include #include 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 #include #include #include #include #include #include #include #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