Neo
Neo

Reputation: 391

Handling large size of Read operation

I am interposing a read operation with my own implementation of read that prints some log and calls the libc read. I am wondering what should be the right way to handle read with a huge nbyte parameter. Since nbyte is size_t, what is the right way to handle out of range read request? From the read manpage:

If the value of nbyte is greater than {SSIZE_MAX}, the result is implementation-defined

What does this mean and if I have to handle a large read request, what should I do?

Upvotes: 1

Views: 354

Answers (5)

Jeremy Huddleston Sequoia
Jeremy Huddleston Sequoia

Reputation: 23623

Being implementation defined means that there is no correct answer, and callers should never do this (because they can’t be certain how it will be handled). Given that you are interposing the syscall, I suggest you just assert(2) that the value is in range. If you end up failing that assert somewhere, fix the calling code to be compliant.

Upvotes: 1

nuggets
nuggets

Reputation: 179

The last parameter of read is the buffer size. It's not the number of bytes to read.

So:

  • if the buffer size you received is lesser than SSIZE_MAX, call the syscall 'read' with buffer size.
  • If the buffer size you received is greater than SSIZE_MAX, 'read' SSIZE_MAX
  • If the read syscall return -1, return -1 too
  • If the read syscall return 0 or less than SSIZE_MAX --> return the sum of bytes read.
  • If the read call return exactly SSIZE_MAX, decrement the buffer size received of SSIZE_MAX
  • and loop (goto "So")

Do not forget to adjust the buffer pointer and to count the total number of bytes read.

Upvotes: 1

Andrew Henle
Andrew Henle

Reputation: 1

Don't change the behavior of the read() call - just wrap the OS-provided call and allow it to do what it does.

ssize_t read( int fd, void *buf, size_t bytes )
{
    ssize_t result;
        .
        .
        .
    result = read_read( fd, buf, bytes );
       .
       .
       .
    return( result );
}

What could you possibly do if you're implementing a 64-bit library a caller passes you a size_t value that's greater than SSIZE_MAX? You can't split that up into anything reasonable anyway.

And if you're implementing a 32-bit library, how would you pass the proper result back if you did split up the read?

Upvotes: 2

You could simply use strace(1) to get some logs of your read syscalls.

In practice the read count is the size of some buffer (in memory), so it is very unusual to have it being bigger than a dozen of megabytes. It is often some kilobytes.

So I believe you should not care about SSIZE_MAX limit in real life

Upvotes: 1

DevSolar
DevSolar

Reputation: 70263

You could break up the one large request into several smaller ones.

Besides, SSIZE_MAX is positively huge. Are you really sure you need to read >2GB of data, in one go?

Upvotes: 2

Related Questions