Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Nov 2010 16:06:40 GMT
From:      Salvatore Sanfilippo <antirez@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/152485: /dev/null seek offset is not reported correctly
Message-ID:  <201011221606.oAMG6ejA073532@red.freebsd.org>
Resent-Message-ID: <201011221610.oAMGAEWe068188@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         152485
>Category:       misc
>Synopsis:       /dev/null seek offset is not reported correctly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 22 16:10:13 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Salvatore Sanfilippo
>Release:        FreeBSD 8
>Organization:
VMware
>Environment:
unfortunately I don't have access to the system where the bug was reported / verified
>Description:
The bug was discovered as a result of a bug in Redis data base Virtual Memory implementation when running on FreeBSD.  Opening /dev/null using the libc standard I/O functions and writing against it more than 4096 bytes (one memory page) will result in the seek reported by ftell() to be modulo 4096 (that is, an incorrect value).

Even if /dev/null is not a standard file it should behave correctly and should be able to retain the current seek for the open file in a reliable way. I can't cite standard but I've the feeling the current behavior is not ok, and it's worth fixing even just because other *BSD kernels and Linux will instead behave in the obvious least-surprising way.
>How-To-Repeat:
#include <stdio.h>

int main(argc, argv) {

    FILE *fp = fopen("/dev/null","w+");
    rewind(fp);
    
    int i, len;
    for (i=1;i<80000;i++) {
        fwrite("t", 1, 1, fp);
        len = ftello(fp);
        if (len != i) {
            printf("Fail on pos: %d, expected to be %d\n", len, i);
            return 1;
        }
    }
    printf("Pos is: %d\n", len);
    fclose(fp);
    return 0;
}

>Fix:
The /dev/null implementation in FreeBSD appears to be optimized for speed, it allocates a single page of memory and reads from it, writes are completely discarded. Apparently there is no handling of the offset. But since I've almost zero clues about the FreeBSD char device API I don't know how a correct implementation should look like.

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011221606.oAMG6ejA073532>