4

I was trying to move a set of 7 files to my computer, via mv g* dir. The command line moved 6 of them, and for the last file gave the following error:

mv: g.tex: Argument list too long

Since the other files, both those before and after it, are already moved, I tried mv g.tex dir. Same error. Moving other files works fine. (Note: g.tex is a file, not a directory.)

Update: Renaming the file via mv also works fine; moving it to another directory on the USB drive also works fine. However, even when I rename it, or move it to another directory on the USB drive, I still cannot move it to my computer.

I tried to cat this file, to copy its contents to the desktop:

cat: g.tex: Argument list too long

What else might be causing this problem?

Update: after comparing output of dtruss with a file which successfully moved, here are the lines of the log which differ:

read(0x3, "\0", 0x20000)         = -1 Err#7
write_nocancel(0x2, "mv: \0", 0x4)       = 4 0
getrlimit(0x1008, 0x7FFF5A00BC78, 0x4)       = 0 0
write_nocancel(0x2, "g.tex\0", 0x5)      = 5 0
write_nocancel(0x2, ": \0", 0x2)         = 2 0
write_nocancel(0x2, "Argument list too long\n\0", 0x17)      = 23 0
unlink("/Users/username/Desktop/Tex/g.tex\0", 0x7FFF5A00B8A0, 0x17)      = 0 0
close(0x3)       = 0 0

From the list of Unix error codes for read:

#define E2BIG        7  /* Argument list too long */

On a successful move, it displays instead:

read(0x3, "Beginning of file contents...", 0x20000)      = 0 0
fstat64_extended(0x3, 0x7FF1F5C02568, 0x7FF1F5C02660)        = 0 0
fstat64(0x4, 0x7FFF5A653EF0, 0x7FF1F5C02660)         = 0 0
fchmod(0x4, 0x180, 0x7FF1F5C02660)       = 0 0
__mac_syscall(0x7FFF8E670D02, 0x52, 0x7FFF5A653E70)      = -1 Err#93
flistxattr(0x4, 0x0, 0x0)        = 0 0
flistxattr(0x3, 0x0, 0x0)        = 23 0
flistxattr(0x3, 0x7FF1F5C02490, 0x17)        = 23 0
fgetxattr(0x3, 0x7FF1F5C02490, 0x0)      = 11 0
fgetxattr(0x3, 0x7FF1F5C02490, 0x7FF1F6001000)       = 11 0
fsetxattr(0x4, 0x7FF1F5C02490, 0x7FF1F6001000)       = 0 0
fstat64_extended(0x4, 0x7FFF5A653628, 0x7FF1F5C02660)        = 0 0
fchmod_extended(0x4, 0xFFFFFF9B, 0xFFFFFF9B)         = 0 0
fchmod(0x4, 0x0, 0xFFFFFF9B)         = 0 0
close(0x3)       = 0 0
fchown(0x4, 0x6300000063, 0x63)      = 0 0
fchmod(0x4, 0x81FF, 0x63)        = 0 0
fchflags(0x4, 0x0, 0x63)         = 0 0
utimes("/Users/aleksander/Desktop/Tex/new_filename\0", 0x7FFF5A654860, 0x63)         = 0 0

Just in case this helps, the remainder of the lines, which match for a successful mv command and for the failed one, right before the differing text quoted above:

open("/dev/dtracehelper\0", 0x2, 0x7FFF53E619B0)         = 3 0
ioctl(0x3, 0x80086804, 0x7FFF53E61938)       = 0 0
close(0x3)       = 0 0
thread_selfid(0x3, 0x80086804, 0x7FFF53E61938)       = 167920154 0
bsdthread_register(0x7FFF8E8710F4, 0x7FFF8E8710E4, 0x2000)       = 1073741919 0
ulock_wake(0x1, 0x7FFF53E6116C, 0x0)         = -1 Err#2
issetugid(0x1, 0x7FFF53E6116C, 0x0)      = 0 0
mprotect(0x10BDA5000, 0x88, 0x1)         = 0 0
mprotect(0x10BDA7000, 0x1000, 0x0)       = 0 0
mprotect(0x10BDBD000, 0x1000, 0x0)       = 0 0
mprotect(0x10BDBE000, 0x1000, 0x0)       = 0 0
mprotect(0x10BDD4000, 0x1000, 0x0)       = 0 0
mprotect(0x10BDD5000, 0x1000, 0x1)       = 0 0
mprotect(0x10BDA5000, 0x88, 0x3)         = 0 0
mprotect(0x10BDA5000, 0x88, 0x1)         = 0 0
getpid(0x10BDA5000, 0x88, 0x1)       = 28838 0
stat64("/AppleInternal/XBS/.isChrooted\0", 0x7FFF53E61028, 0x1)      = -1 Err#2
stat64("/AppleInternal\0", 0x7FFF53E610C0, 0x1)      = -1 Err#2
csops(0x70A6, 0x7, 0x7FFF53E60B50)       = 0 0
sysctl([CTL_KERN, 14, 1, 28838, 0, 0] (4), 0x7FFF53E60CA8, 0x7FFF53E60CA0, 0x0, 0x0)         = 0 0
ulock_wake(0x1, 0x7FFF53E610D0, 0x0)         = -1 Err#2
csops(0x70A6, 0x7, 0x7FFF53E60430)       = 0 0
stat64("/Users/aleksander/Desktop/Tex\0", 0x7FFF53E62B88, 0x7FFF53E60430)    = 0 0
lstat64("g.tex\0", 0x7FFF53E62AF8, 0x7FFF53E60430)       = 0 0
lstat64("/Users/aleksander/Desktop/Tex\0", 0x7FFF53E62A68, 0x7FFF53E60430)   = 0 0
stat64("g.tex\0", 0x7FFF53E62AF8, 0x7FFF53E60430)        = 0 0
stat64("/Users/aleksander/Desktop/Tex/g.tex\0", 0x7FFF53E62A68, 0x7FFF53E60430) = -1 Err#2
access("/Users/aleksander/Desktop/Tex/g.tex\0", 0x0, 0x7FFF53E60430)         = -1 Err#2
rename("g.tex\0", "/Users/aleksander/Desktop/Tex/g.tex\0")       = -1 Err#18
stat64("/\0", 0x7FFF53E5FB60, 0x7FFF53E60430)        = 0 0
open_nocancel(".\0", 0x0, 0x1)       = 3 0
fstat64(0x3, 0x7FFF53E5F900, 0x1)        = 0 0
fcntl_nocancel(0x3, 0x32, 0x7FFF53E61980)        = 0 0
close_nocancel(0x3)      = 0 0
stat64("/Volumes/NO NAME\0", 0x7FFF5A00A870, 0x7FFF5A00C980)         = 0 0
stat64("/Volumes/NO NAME\0", 0x7FFF5A00AB60, 0x7FFF5A00C980)         = 0 0
getattrlist("/Volumes/NO NAME/g.tex\0", 0x7FFF8E715B04, 0x7FFF5A00C470)      = 0 0
statfs64(0x7FFF5A00C980, 0x7FFF5A00CD88, 0x7FFF5A00C470)         = 0 0
lstat64("g.tex\0", 0x7FFF5A00C8F0, 0x7FFF5A00C470)       = 0 0
open("g.tex\0", 0x0, 0x0)        = 3 0
open("/Users/aleksander/Desktop/Tex/g.tex\0", 0xE01, 0x0)        = 4 0
fstatfs64(0x4, 0x7FFF5A00BFF8, 0x0)      = 0 0

xattr -l g.tex doesn't give any output. ls -l g.tex yields:

-rwxrwxrwx 1 username staff 159939 Aug 15 11:54 g.tex

mount yields:

/dev/disk5s1 on /Volumes/NO NAME (msdos, local, nodev, nosuid, noowners)
  • You likely have filenames with - in them, or some other special character. Try mv -- g* dir – Jesse_b Aug 15 '17 at 14:48
  • Nope, no filenames with special characters. Your suggestion still yielded the same error. – Alex Aug 15 '17 at 14:50
  • Try to ls | cat to be sure, maybe it has a line break in the filename? – Jesse_b Aug 15 '17 at 14:51
  • @Jesse_b I just tried that-- all these files are ones I created by hand, so wouldn't have that. – Alex Aug 15 '17 at 14:52
  • 1
    You might use strace(1), perhaps as strace mv, to understand what system call is giving E2BIG as errno(3). You should edit your question to give the exact command which failed; you could also replace mv by echo to understand how is g* expanded – Basile Starynkevitch Aug 15 '17 at 15:06
5

E2BIG is not one of the errors that read(2) may return. It looks like a bug in the kernel.

Pure speculation, but it could be down to some corruption on the file system and the macOS driver for the FAT filesystem returning that error upon encountering that corruption which eventually makes it through to the return of read.

In any case, it looks like you've taken the investigation as far as it gets. Going further would require dissecting the file system and the kernel driver code.

You could have a look at the kernel logs to see if there's more information there. You could try mounting the FS on a different OS. Or use the GNU mtools to access that FAT filesystem.

You could also report the problem to Apple as at least a documentation issue (to include E2BIG as one of the possible error codes, and the conditions upon which it may be returned).

  • 2
    @Alex, issue man 2 read on your system. Towards the bottom of the manual page should be a list of all possible errno values, and the conditions under which that errno will be set. – user4556274 Aug 15 '17 at 19:00
  • What would I do, once I access that FS via mtools? Which kernel logs would contain info about this? I am curious to get down to the bottom of this... – Alex Aug 15 '17 at 19:06
2

Figured out how to solve this. I installed GNU mv, via macPorts. That mv was able to move the file from the USB drive to my computer, without returning the E2BIG error. I wish I would have dtrussed it, to see how it got around the error return from the read.

It turned out that the file pointer was slightly corrupted-- so, the file that got copied started 128KB earlier than where it should have started, but the rest of the file was intact (of course, the last 128KB also got chopped off.)

Lesson to be learned: the native (BSD) utilities on a Mac run a different algorithm than their GNU counterparts-- so when one fails, always try the other.

  • GNU mv will do read()s and write()s just the same. Given that the default chunk size is 128K, I suspect it just ignored the error of the first read() (if it did without reporting an error, I would call that a bug) – Stéphane Chazelas Aug 16 '17 at 15:23
  • That would be a logical explanation if the result was the file starting at position 128K. However, the result was the file starting at position negative 128K. So basically, 128K of junk, and then the file, minus the last 128K of it (since the filesize had to remain the same). – Alex Aug 16 '17 at 16:39
  • I'm not sure what's the bigger bug-- read returning E2BIG, or not reporting an error when there is one so unexpected. :-) – Alex Aug 16 '17 at 16:41
  • Anyway, read() returns the number of bytes read. mv has to take that number into account. It's hard to imagine that it could mistakenly take -1 as meaning a full buffer was read (as if it was 131072) and write the buffer (with whatever garbage was in it) to the destination file. Possibly on macOS GNU mv uses mmap() or some macOS-specific way to read the data that triggers a different bug. Can you try dtruss mv on a test file to see how it copies the data across? – Stéphane Chazelas Aug 16 '17 at 17:44
  • In addition to the read commands of the BSD mv, it also has the following: sysctl([CTL_HW, 7, 0, 0, 0, 0] (2), 0x7FFF9754DE00, 0x7FFF56608570, 0x0, 0x0) = 0 0, madvise(0x10976A000, 0x21000, 0x9) = 0 0, lseek(0x0, 0x0, 0x1) = 221838 0, close_nocancel(0x0) = 0 0, and a few similar commands. Not sure which of these would make the difference... – Alex Aug 16 '17 at 20:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.