Repository: borgbackup/borg

Issue:
attrs: [Errno 1] Operation not permitted: '<FD 7>'
<!--
Thank you for reporting an issue.

*IMPORTANT* -  *before* creating a new issue please look around:
 - Borgbackup documentation: http://borgbackup.readthedocs.io/en/stable/index.html
 - FAQ: https://borgbackup.readthedocs.io/en/stable/faq.html
 and
 - open issues in Github tracker: https://github.com/borgbackup/borg/issues
  
If you cannot find a similar problem, then create a new issue.

Please fill in as much of the template as possible.
-->

## Have you checked borgbackup docs, FAQ, and open Github issues?

Yes

## Is this a BUG / ISSUE report or a QUESTION?

Issue

## System information. For client/server mode post info for both machines.

#### Your borg version (borg -V).
borg 1.1.9 on the server being backed up
borg 1.1.7 on the server with the remote repository

#### Operating system (distribution) and version.
centos 7 on the server being backed up
Linux synology on the server with the remote repository

#### Hardware / network configuration, and filesystems used.
ext4 on both

#### How much data is handled by borg?
16 GB original size

#### Full borg commandline that lead to the problem (leave away excludes and passwords)
`borg extract /path/to/repo::my-files home/USERNAME/src`

## Describe the problem you're observing.
I run the above command to extract some files from a certain path and I get the error
```
attrs: [Errno 1] Operation not permitted: '<FD 7>'
```
Even though I see the error when extracting, I check the file afterwards and it has been extracted and the size is normal. Then why do I see this error? Could it mean that the file is corrupted?

#### Can you reproduce the problem? If so, describe how. If not, describe troubleshooting steps you took before opening the issue.
I run `borg create` on the centos server. The repository is remote on the synology. The backup run succesfully. Then when I am extracting on synology, I see the error.

#### Include any warning/errors/backtraces from the system logs
No logs on synology.
<!--

If this complaint relates to borg performance, please include CRUD benchmark
results and any steps you took to troubleshoot.
How to run benchmark: http://borgbackup.readthedocs.io/en/stable/usage/benchmark.html

*IMPORTANT* - Please mark logs and text output from terminal commands 
or else Github will not display them correctly. 
An example is provided below.

Example:
```
this is an example how log text should be marked (wrap it with ```)
```
-->



Discussion:
try to reproduce with a current borg version (to which you want to upgrade anyway, see changelog).

also try as root.

"attrs" means that it happens when trying to set xattrs (or ACLs or selinux stuff). That needs to be supported by your filesystem to work.
I got this too. Running 1.1.11 everywhere and backup to Borgbase.

Backup is created on a Centos 7 with SELinux set to enforcing.

I tested by running a borg docker image on my docker-for-mac (also 1.1.11) and against the same borgbase remote.

When I ran the same restore command on the Centos 7 host, no errors were given. File was always extracted OK, regardles of the env/error.
> "attrs" means that it happens when trying to set xattrs (or ACLs or selinux stuff). That needs to be supported by your filesystem to work.

Oh. Could it be possible to detect this in Borg code and maybe tell the user that some attrs couldn't be restored, and the usual culprit being that current fs not supporting some attrs.

It also threw me off for a while, I tought the extract command had errored, especially when it says Errno 1 and not warning. Error means non-recoverable usually. I only checked if the file was extracted when someone in one of these issues mentioned that the file did extract OK.
True, I restored a backup and even though each and every file had this Error, the restored backup was complete.
a general thing to check/improve here: it refers to an FD number, does it also show the filename? if not, we should find some way to do that. this is especially an issue in master branch, where a lot of stuff happens based on the FD (and not the filename).
Indeed it shows the full path and filename before the `[Errno 1] Operation not permitted: '<FD num>'`

Resolving patch:
diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py
--- a/src/borg/testsuite/archiver.py
+++ b/src/borg/testsuite/archiver.py
@@ -1370,15 +1370,15 @@ def patched_setxattr_EACCES(*args, **kwargs):
             input_abspath = os.path.abspath('input/file')
             with patch.object(xattr, 'setxattr', patched_setxattr_E2BIG):
                 out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING)
-                assert '>: Value or key of extended attribute user.attribute is too big for this filesystem\n' in out
+                assert ': when setting extended attribute user.attribute: too big for this filesystem\n' in out
             os.remove(input_abspath)
             with patch.object(xattr, 'setxattr', patched_setxattr_ENOTSUP):
                 out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING)
-                assert '>: Extended attributes are not supported on this filesystem\n' in out
+                assert ': when setting extended attribute user.attribute: xattrs not supported on this filesystem\n' in out
             os.remove(input_abspath)
             with patch.object(xattr, 'setxattr', patched_setxattr_EACCES):
                 out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING)
-                assert '>: Permission denied when setting extended attribute user.attribute\n' in out
+                assert ': when setting extended attribute user.attribute: Permission denied\n' in out
             assert os.path.isfile(input_abspath)
 
     def test_path_normalization(self):
diff --git a/src/borg/xattr.py b/src/borg/xattr.py
--- a/src/borg/xattr.py
+++ b/src/borg/xattr.py
@@ -133,19 +133,19 @@ def set_all(path, xattrs, follow_symlinks=False):
                 path_str = '<FD %d>' % path
             else:
                 path_str = os.fsdecode(path)
+            msg_format = '%s: when setting extended attribute %s: %%s' % (path_str, k_str)
             if e.errno == errno.E2BIG:
-                logger.warning('%s: Value or key of extended attribute %s is too big for this filesystem' % (
-                               path_str, k_str))
+                err_str = 'too big for this filesystem'
             elif e.errno == errno.ENOTSUP:
-                logger.warning('%s: Extended attributes are not supported on this filesystem' % path_str)
-            elif e.errno == errno.EACCES:
-                # permission denied to set this specific xattr (this may happen related to security.* keys)
-                logger.warning('%s: Permission denied when setting extended attribute %s' % (path_str, k_str))
+                err_str = 'xattrs not supported on this filesystem'
             elif e.errno == errno.ENOSPC:
                 # ext4 reports ENOSPC when trying to set an xattr with >4kiB while ext4 can only support 4kiB xattrs
                 # (in this case, this is NOT a "disk full" error, just a ext4 limitation).
-                logger.warning('%s: No space left on device while setting extended attribute %s (len = %d)' % (
-                               path_str, k_str, len(v)))
+                err_str = 'no space left on device [xattr len = %d]' % (len(v),)
             else:
-                raise
+                # generic handler
+                # EACCES: permission denied to set this specific xattr (this may happen related to security.* keys)
+                # EPERM: operation not permitted
+                err_str = os.strerror(e.errno)
+            logger.warning(msg_format % err_str)
     return warning


Test patch: