www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/10/12/16:05:40

Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <3BC74CBE.EC9CBF9F@phekda.freeserve.co.uk>
Date: Fri, 12 Oct 2001 21:04:14 +0100
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.19 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: Resend: DJGPP and files > 2GB
References: <200110120744 DOT JAA24662 AT lws256 DOT lu DOT erisoft DOT se>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Martin Stromberg wrote:
> 
> Richard said:
> > I'm not convinced by your argument. Consider relative seeks:
> >
> > lseek(fd, SEEK_SET, 2GB - 10);
> > lseek(fd, SEEK_CUR, 1GB);
> >
> > Now I want to seek backwards 2.5GB. How would I do that? How does
> > lseek
> 
> lseek(fd, SEEK_CUR, -2.5GB) (or lseek(fd, SEEK_CUR, -2.5GB + 2^32),
> it's the same thing).
> 
> > know which direction I want to go for relative seeks with |offset| >
> 2GB?
> 
> It doesn't and doesn't need to as everything is done mod 2^32. _Or_
> perhaps it does and acts differently depending on current position and
> seek offset.

Ah, OK, I think I see what you're saying now. Sorry for being a little
slow on the uptake. Relative seeks seem to be handled mod 2^32 too. Please
find my test program below, that tests out relative seeks - it relies on
the fact that lseek passes the offset directly to the DOS interrupt.

Ralph Brown's interrupt list mentions that it's possible to set the file
position before the start of the file (i.e. off_t is negative). With
support for files greater than 2GB, I guess this isn't true with >2GB
support, since the negative off_t values actually mean offsets >= 2GB.

BTW I just discovered that 'du' is broken by stat's st_size member
wrapping. I'll look at adding basic support for LFS this weekend.
 
> > Incidentally, why does lseek check whether the file descriptor is a
> > pipe or not, after it's done the INT21h call? Shouldn't it do it
> > before the interrupt?
> 
> Don't know.

Mark, do you know why this is? It seems to be your change. Perhaps it was
added here, because the fd properties code was already in that part of the
function. This problem is also present in llseek.

I think the check belongs after the FSEXT call, but before the DOS
interrupt.

Thanks, bye, Rich =]

---START bigseek.c---
/*
 * bigseek.c
 * Try big relative seeks with DJGPP CVS (aka 2.04?)
 * Written by Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>

int
main (int argc, char *argv[])
{  
  char *filename;
  struct stat sbuf;
  unsigned long sz;
  ssize_t n;
  char buf[4];
  off_t o;
  int fd;

  /* 2GB + 100MB */
  const unsigned long big_offset = (1024UL * 1024UL * 1024UL * 2UL)
                                 + (1024UL * 1024UL * 100UL);

  /* 2GB + 10MB */
  unsigned long big_offset2 = (1024UL * 1024UL * 1024UL * 2UL)
                            + (1024UL * 1024UL * 10UL);

  assert(big_offset2 < big_offset);

  if (argc < 2) {
    fprintf(stderr, "Oi! Where's me file?\n");
    return(EXIT_FAILURE);
  }

  /* Does the file exist? How big is it? */
  filename = argv[1];

  if (stat(filename, &sbuf) < 0) {
    perror(argv[0]);
    return(EXIT_FAILURE);
  }

  if (!S_ISREG(sbuf.st_mode)) {
    fprintf(stderr, "%s is not a regular file!\n", filename);
    return(EXIT_FAILURE);
  }

  /* Check the file's bigger than 2GB. */
  sz = (unsigned long) sbuf.st_size;

  if (sz <= big_offset) {
    fprintf(stderr, "%s is not bigger than %lu (%luMB)!\n",
	    filename, big_offset, big_offset / (1024UL * 1024UL));
    return(EXIT_FAILURE);
  }

  /* Now open the file and try out some big relative seeks (> 2GB
movement). */
  fd = open(argv[1], O_RDONLY|O_BINARY);

  o = lseek(fd, big_offset, SEEK_SET);
  printf("Offset %lu (desired = %lu)\n", (unsigned long) o, big_offset);
  o = lseek(fd, big_offset2, SEEK_CUR);
  printf("Offset %lu (desired = %lu)\n", (unsigned long) o,
	 big_offset + big_offset2);

  printf("big_offset - big_offset2 = %lu\n", big_offset - big_offset2);
  printf("big_offset + big_offset2 = %lu\n", big_offset + big_offset2);
  printf("(off_t) big_offset2 = %d\n", (off_t) big_offset2);

  /* Return to the start, seek to beyond 2GB, try a read. Then try
   * a large (2GB - 1) backwards seek. */
  o = lseek(fd, 0, SEEK_SET);
  printf("Offset %d\n", o);
  o = lseek(fd, big_offset, SEEK_CUR);
  printf("Offset %d\n", o);

  n = read(fd, buf, sizeof(buf));
  if (n < sizeof(buf)) {
    fprintf(stderr, "Read at offset %d (aka %lu?) failed\n",
	    o, (unsigned long) o);
    close(fd);
    return(EXIT_FAILURE);
  } else {
    printf("Read at offset %d (aka %lu?) OK\n", o, (unsigned long) o);
  }
  o = lseek(fd, -sizeof(buf), SEEK_CUR); /* Return to pre-read position */

  o = lseek(fd, -(off_t)((1024UL * 1024UL * 1024UL * 2UL) - 1UL),
SEEK_CUR);
  printf("Offset %d\n", o);

  printf("big_offset - 2GB - 1 = %lu\n",
	 big_offset - ((1024UL * 1024UL * 1024UL * 2UL) - 1UL));

  /* Done with file */
  close(fd);

  return(EXIT_SUCCESS);
}
---END bigseek.c---

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019