Bug 15639

Summary: msdosfs can't read large (3.8gig) files
Product: Base System Reporter: kientzle
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.3-RELEASE   
Hardware: Any   
OS: Any   

Description kientzle 1999-12-23 05:40:00 UTC
How to transfer a 3.8gig file from a distant Windows
computer to a FreeBSD machine?

I have a (fairly important) file sent me on a Windows-formatted
hard disk.  When I 'mount_msdos /dev/wd3s1' and then try
to 'cp /mnt/BigFile.avi /usr/tmp', I end up with a 0-byte
file in /usr/tmp.

Fix: 

Note: if some knowledgable soul can give me pointers
to likely culprits in the msdosfs code, I'd happily
experiment.  This is a very important file, and I
need to access it very soon.
Comment 1 sprice 1999-12-23 19:50:29 UTC
---------- Forwarded message ----------
Date: Thu, 23 Dec 1999 11:40:40 -0800
From: Tim Kientzle <kientzle@acm.org>
To: gnats-admin@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG
Subject: Re: kern/15639: msdosfs can't read large (3.8gig) files

gnats-admin@FreeBSD.org wrote:
> 
> Thank you very much for your problem report.
> It has the internal identification `kern/15639'.
> The individual assigned to look at your
> report is: freebsd-bugs.
> 
> >Category:       kern
> >Responsible:    freebsd-bugs
> >Synopsis:       msdosfs can't read large (3.8gig) files
> >Arrival-Date:   Wed Dec 22 21:40:00 PST 1999

I've since found a fix for this problem.  The bug
is in 'msdosfs_vnops.c', in the function
'msdosfs_read'.

Early in that function, it computes fileSize minus
requestedOffset, and stores the difference into a
signed int.  With very large files, that int can
overflow.  A better approach is to
make 'diff' an unsigned long, use a direct comparison
for the initial test, and then be cautious about comparing
'diff' to the signed 'n':

                if (dep->de_FileSize <= uio->uio_offset)
                        return (0);
                /* Note: diff can be as large as 4gig! */
                diff = dep->de_FileSize - uio->uio_offset;
                /* Avoid setting n to a negative value */
                if ((diff < n) && (diff < LONG_MAX))
                        n = diff;

This change allowed me to successfully copy a 3.8gig file from
an MSDOS-formatted hard disk.

				- Tim Kientzle
Comment 2 Boris Popov freebsd_committer freebsd_triage 2000-01-13 06:35:26 UTC
State Changed
From-To: open->closed

Fixed along with other 2GB bugs. Thanks!