Date: Mon, 3 Jun 2013 07:14:46 GMT From: Akinori MUSHA <knu@FreeBSD.org> To: freebsd-gnats-submit@FreeBSD.org Subject: standards/179248: A return value of telldir(3) only seekable for once Message-ID: <201306030714.r537EkKr040579@oldred.freebsd.org> Resent-Message-ID: <201306030720.r537K0Af067488@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 179248 >Category: standards >Synopsis: A return value of telldir(3) only seekable for once >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Jun 03 07:20:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Akinori MUSHA >Release: FreeBSD 9.1-STABLE >Organization: >Environment: FreeBSD 9.1-STABLE #29 r250273: Mon May 6 01:09:00 JST 2013 (amd64) >Description: Our implementation of telldir(3)/seekdir(3) is not POSIX compliant in that a value obtained from telldir(3) is invalidated after calling seekdir(3) and then readdir(3). IEEE Std 1003.1, 2008/2013 says that only a call of rewinddir(3) may invalidate the location values returned by telldir(3): If the value of loc was not obtained from an earlier call to telldir(), or if a call to rewinddir() occurred between the call to telldir() and the call to seekdir(), the results of subsequent calls to readdir() are unspecified. >How-To-Repeat: % cat ../dirtest.c #include <stdio.h> #include <string.h> #include <sys/types.h> #include <dirent.h> int main(void) { DIR *dirp; struct dirent *dp; long pos; if ((dirp = opendir(".")) == NULL) return 1; printf("telldir = %ld\n", telldir(dirp)); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", telldir(dirp)); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", telldir(dirp)); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", pos = telldir(dirp)); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", telldir(dirp)); printf("seekdir to %ld\n", pos); seekdir(dirp, pos); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", telldir(dirp)); printf("seekdir to %ld\n", pos); seekdir(dirp, pos); if ((dp = readdir(dirp)) == NULL) return 1; printf("readdir = %s\n", dp->d_name); printf("telldir = %ld\n", telldir(dirp)); (void)closedir(dirp); return 0; } % make ../dirtest cc -O2 -pipe -g -march=core2 ../dirtest.c -o ../dirtest % ls -al total 35 drwxr-xr-x 2 knu knu 6 Jun 3 15:39 . drwx------ 11 knu knu 53 Jun 3 15:39 .. -rw-r--r-- 1 knu knu 0 Jun 3 15:39 aaa -rw-r--r-- 1 knu knu 0 Jun 3 15:39 bbb -rw-r--r-- 1 knu knu 0 Jun 3 15:39 ccc -rw-r--r-- 1 knu knu 0 Jun 3 15:39 ddd % ../dirtest telldir = 1 readdir = . telldir = 2 readdir = .. telldir = 3 readdir = aaa telldir = 4 readdir = ccc telldir = 5 seekdir to 4 readdir = ccc # <= OK telldir = 6 seekdir to 4 readdir = bbb # <= FAIL telldir = 7 >Fix: I don't have a quick fix for this, as it may need a revamp of how the location thing is defined. NetBSD seems to have a different implementation which doesn't have this problem. However, I'm not sure if theirs is flawless esp. wrt memory management. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306030714.r537EkKr040579>