File: mergeall-products/unzipped/docetc/miscnotes/mac-chflags-error22.txt
Mac's chflags() seems to throw error 22=Invalid Argument, when trying to
copy a file's flags from a Mac HFS+ drive to a non-Mac (exFAT) drive.
The flags were added by TextEdit; they record encoding type, and cause
every file edited in TextEdit to trigger an error message in mergeall,
even though they copy correctly in both content and timestamps. This
fails on an uncaught exception in the very last step of shutil.copystat(),
(used by cpall.py) after all else has been copied correctly.
Solution: redefine os.chflags() to try original, catch and ignore
errno.EINVAL on Macs only, and allow all others to pass. Could
delete os.chflags() completely, but may be useful when TO is a
Mac drive. Could also verify that times were copied over
correctly and reraise if not, but this seems too much work.
Update: Mac extended attributes can also arise in other contexts,
so this is a general concern; another example from PyEdit:
$ ls -l@ Whitepaper.html
-rwxrwxrwx@ 1 blue wheel 90072 May 30 18:46 Whitepaper.html
com.apple.quarantine 29
$ xattr Whitepaper.html
com.apple.quarantine
$ xattr -p com.apple.quarantine Whitepaper.html
0002;5928a690;Microsoft Word;
-------------------------------------------------------------------------------
After this mergeall error was reported:
-------------------------------------------------------------------------------
# force difference...
$ rm /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
# mergeall report...
*Resolving tree differences
Skipping system cruft (metadata) files in FROM folders
**Error copying FROM file: skipped /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
<class 'OSError'> [Errno 22] Invalid argument: '/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt'
Phase runtime: 0.9569850449915975
-------------------------------------------------------------------------------
Files same in content and modtimes, but extended flags differ
-------------------------------------------------------------------------------
$ ls -l /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ diff /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ xattr /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding
$ xattr /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
xattr: /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt: No such xattr: com.apple.TextEncoding
$
$ ls -lO@ /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel - 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
l$ ls -lO@ /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff - 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
-------------------------------------------------------------------------------
Fails in the shell too, with same error -- BUT seems to copy flags anyhow...
-------------------------------------------------------------------------------
$ cp -p /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
cp: fchflags: /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt: Invalid argument
$
$ xattr /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding
$ xattr /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding
$
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$
-------------------------------------------------------------------------------
What Python shutil.copystat() fails on: does not catch errorno 22 = EINVAL
-------------------------------------------------------------------------------
$ py3
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, stat
>>> st = os.stat('/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt')
>>> os.chflags('/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt', st.st_flags)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument: '/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt'
>>>
>>> os.chflags('/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt', st.st_flags) # but Mac drive works
>>> ^D
$
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
------------------------------------------------------------------------------
The error code in Python
------------------------------------------------------------------------------
>>> import errno
>>> dir(errno)
['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EAFNOSUPPORT', 'EAGAIN', 'EALREADY', 'EAUTH', 'EBADARCH', 'EBADEXEC', 'EBADF', 'EBADMACHO', 'EBADMSG', 'EBADRPC', 'EBUSY', 'ECANCELED', 'ECHILD', 'ECONNABORTED', 'ECONNREFUSED', 'ECONNRESET', 'EDEADLK', 'EDESTADDRREQ', 'EDEVERR', 'EDOM', 'EDQUOT', 'EEXIST', 'EFAULT', 'EFBIG', 'EFTYPE', 'EHOSTDOWN', 'EHOSTUNREACH', 'EIDRM', 'EILSEQ', 'EINPROGRESS', 'EINTR', 'EINVAL', 'EIO', 'EISCONN', 'EISDIR', 'ELOOP', 'EMFILE', 'EMLINK', 'EMSGSIZE', 'EMULTIHOP', 'ENAMETOOLONG', 'ENEEDAUTH', 'ENETDOWN', 'ENETRESET', 'ENETUNREACH', 'ENFILE', 'ENOATTR', 'ENOBUFS', 'ENODATA', 'ENODEV', 'ENOENT', 'ENOEXEC', 'ENOLCK', 'ENOLINK', 'ENOMEM', 'ENOMSG', 'ENOPOLICY', 'ENOPROTOOPT', 'ENOSPC', 'ENOSR', 'ENOSTR', 'ENOSYS', 'ENOTBLK', 'ENOTCONN', 'ENOTDIR', 'ENOTEMPTY', 'ENOTSOCK', 'ENOTSUP', 'ENOTTY', 'ENXIO', 'EOPNOTSUPP', 'EOVERFLOW', 'EPERM', 'EPFNOSUPPORT', 'EPIPE', 'EPROCLIM', 'EPROCUNAVAIL', 'EPROGMISMATCH', 'EPROGUNAVAIL', 'EPROTO', 'EPROTONOSUPPORT', 'EPROTOTYPE', 'EPWROFF', 'ERANGE', 'EREMOTE', 'EROFS', 'ERPCMISMATCH', 'ESHLIBVERS', 'ESHUTDOWN', 'ESOCKTNOSUPPORT', 'ESPIPE', 'ESRCH', 'ESTALE', 'ETIME', 'ETIMEDOUT', 'ETOOMANYREFS', 'ETXTBSY', 'EUSERS', 'EWOULDBLOCK', 'EXDEV', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'errorcode']
>>> errno.errorcode[22]
'EINVAL'
>>> errno.EINVAL
22
------------------------------------------------------------------------------
A fuller example: WITHOUT (BEFORE CPALL.PY FIX)
------------------------------------------------------------------------------
$ rm /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
# rerun mergeall via its GUI, same error as above: files+times same, flags NOT copied
*Resolving tree differences
Skipping system cruft (metadata) files in FROM folders
**Error copying FROM file: skipped /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
<class 'OSError'> [Errno 22] Invalid argument: '/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt'
$ ls -lO@ /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel - 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
$ ls -lO@ /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff - 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
# recreate error interctively: same results
$ py3
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, stat
>>> st = os.stat('/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt')
>>> os.chflags('/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt', st.st_flags)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument: '/Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt'
>>> ^D
$ ls -lO@ /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel - 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
$ ls -lO@ /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff - 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
xattr: /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt: No such xattr: com.apple.TextEncoding
$
# same error at shell: BUT flags seem to be copied over anyhow (unlike Python)
$ cp -p /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
cp: fchflags: /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt: Invalid argument
$
$ ls -lO@ /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel - 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
$ ls -lO@ /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue staff - 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$
------------------------------------------------------------------------------
POST CPALL.PY FIX
------------------------------------------------------------------------------
$ rm /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
*Resolving tree differences
Skipping system cruft (metadata) files in FROM folders
copied new FROM file, /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
Phase runtime: 0.015111149987205863
$ ls -l /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ diff /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ ls -lO@ /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx@ 1 blue wheel - 5295 Dec 5 11:36 /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding 15
$ ls -lO@ /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
-rwxrwxrwx 1 blue staff - 5295 Dec 5 11:36 /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$
$ xattr -p com.apple.TextEncoding /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
utf-8;134217984
$ xattr -p com.apple.TextEncoding /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
xattr: /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt: No such xattr: com.apple.TextEncoding
$
$ xattr /MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
com.apple.TextEncoding
$ xattr /Volumes/SAVAGEX256G/MY-STUFF/__more__/Gadgets/mac/CHEAT-SHEET.txt
$