[Prev][Next][Index][Thread]

possibly a bug in generic_file_read



It appears that there is a bug in generic_file_read in the linux/fs
code.  The file position index is never updated, so repeated calls to
fill a buffer, e.g., with the read system call, always fill from the
beginning of the file.  Here is a diff for linux/fs/dev.c that seems to
fix the problem.

*** dev.c       Fri Jan  1 12:22:06 1999
--- dev.c.0     Fri Jan  1 12:19:37 1999
***************
*** 431,437 ****
        }
  
        retval = count - bytesleft;
-         filp->f_pos += retval;
   done:
        if (bytesleft != count && ! IS_RDONLY(inode)) {
                /* Then we have read something -- update the atime. */
--- 431,436 ----

I have also attached a test program that exposes the bug.

Mike
/*
 * Copyright (c) 1996, 1998 University of Utah and the Flux Group.
 * All rights reserved.
 * 
 * This file is part of the Flux OSKit.  The OSKit is free software, also known
 * as "open source;" you can redistribute it and/or modify it under the terms
 * of the GNU General Public License (GPL), version 2, as published by the Free
 * Software Foundation (FSF).  To explore alternate licensing terms, contact
 * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
 * 
 * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
 * received a copy of the GPL along with the OSKit; see the file COPYING.  If
 * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
 */
/*
 * Example of using the fsread library.
 *
 * It opens a file "/etc/passwd" and dumps it out.
 *
 * You will need to make sure DISK_NAME, PART_NAME, and FILE_NAME are
 * appropriate.
 */

#define DISK_NAME       "sda"
#define PART_NAME       "b"
#define FILE_NAME       "/etc/passwd"

#include <oskit/dev/dev.h>
#include <oskit/diskpart/diskpart.h>
#include <oskit/io/blkio.h>
#include <oskit/dev/linux.h>
#include <oskit/fs/linux.h>
#include <oskit/fs/read.h>
#include <oskit/principal.h>
#include <oskit/c/fcntl.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <fs.h>

/* Partition array, filled in by the diskpart library. */
#define MAX_PARTS 30
static diskpart_t part_array[MAX_PARTS];

#define CHECK(err, pred, f, args) ({                  \
        (err) = f args;                 \
        if (pred) panic(#f" failed: %s (0x%lx)", strerror(err), (err));\
})

/* Identity of current client process. */
static oskit_principal_t *cur_principal;

#define MYBUFSIZE 20

int
main(int argc, char **argv)
{
        char buf[MYBUFSIZE];
        oskit_blkio_t *disk;
        oskit_blkio_t *part;
        oskit_u32_t i;
        oskit_error_t err;
        char *diskname = DISK_NAME;
        char *partname = PART_NAME;
        char *filename = FILE_NAME;
        int nparts;
        oskit_filesystem_t *out_fs;
        int fd, n;
        oskit_identity_t id;
        oskit_dir_t *dir;

        printf(">>>Initializing devices...\n");
        oskit_dev_init();
        oskit_linux_init_ide();
        oskit_linux_init_scsi();

        printf(">>>Probing devices...\n");
        oskit_dev_probe();

        printf(">>>Establishing client identity\n");
        id.uid = 0;
        id.gid = 0;
        id.ngroups = 0;
        id.groups = 0;
        CHECK(err, err, oskit_principal_create, (&id, &cur_principal));
        CHECK(err, err, oskit_linux_block_open, 
              (diskname, OSKIT_DEV_OPEN_READ, &disk));

        nparts = diskpart_blkio_get_partition(disk, part_array, MAX_PARTS);
        assert(nparts > 0);
        CHECK(err, !err, 
              diskpart_blkio_lookup_bsd_string, 
              (part_array, partname, disk, &part));
        oskit_blkio_release(disk); /* partition has a ref */

        printf(">>>Trying open\n");
        fs_linux_init();
        assert(fs_linux_mount(part,OSKIT_FS_RDONLY,&out_fs) == 0);
/*      oskit_blkio_release(part);  can we release the partition now? */
        CHECK(err, err, oskit_filesystem_getroot, (out_fs, &dir));
        CHECK(err, err, fs_init, (dir));
        CHECK(fd, fd == -1, open, (filename, O_RDONLY));
        printf ("open fd = %d\n", fd);
        do {
          n = read(fd, buf, MYBUFSIZE);
          printf("n = %d\n", n);
          for (i = 0; i < n; i++) putchar(buf[i]);
        } while (n == MYBUFSIZE);

        return 0;
}

oskit_error_t
oskit_get_call_context(const struct oskit_guid *iid, void **out_if)
{
    if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
        memcmp(iid, &oskit_principal_iid, sizeof(*iid)) == 0) {
        *out_if = cur_principal;
        oskit_principal_addref(cur_principal);
        return 0;
    } else {
        printf("crapped out in oskit_get_call_context\n");
        exit (1);
    }
}


Follow-Ups: