use ENOTTY to report unsupported ioctl, fix listxattr

Summary:
The unix `patch` command attempts to issue an `FS_IOC_GETFLAGS`
ioctl and blows up when we return `ENOSYS`.  The man page for ioctl says:

```
   ENOTTY The specified request does not apply to the kind of object that
   the file descriptor fd references.
```

so let's return that error code to ioctl.

In addition, the integration test I added for this trips up when it calls
`llistxattr` on the file; turns out we don't need to insert the
`fuse_getxattr_out` when we're returning the attribute list and that it
is only needed when measuring up the required length, so let's move
things around to resolve this and make it clearer.

Reviewed By: chadaustin

Differential Revision: D6685568

fbshipit-source-id: 81963ffe9af30db5634e5e96b7a8aa1485859d65
This commit is contained in:
Wez Furlong 2018-01-09 12:28:30 -08:00 committed by Facebook Github Bot
parent b0fac29b0b
commit 6db8db6dfd
2 changed files with 47 additions and 10 deletions

View File

@ -626,6 +626,12 @@ void FuseChannel::processSession() {
// a way to fulfil the promise
break;
case FUSE_IOCTL:
// Rather than the default ENOSYS, we need to return ENOTTY
// to indicate that the requested ioctl is not supported
replyError(*header, ENOTTY);
break;
default: {
auto handlerIter = handlerMap.find(header->opcode);
if (handlerIter != handlerMap.end()) {
@ -1033,12 +1039,11 @@ folly::Future<folly::Unit> FuseChannel::fuseListXAttr(
count += attr.size();
}
fuse_getxattr_out out;
memset(&out, 0, sizeof(out));
out.size = count;
if (size == 0) {
// caller is asking for the overall size
fuse_getxattr_out out;
memset(&out, 0, sizeof(out));
out.size = count;
request.sendReply(out);
} else if (size < count) {
XLOG(DBG7) << "LISTXATTR input size is " << size << " and count is "
@ -1048,13 +1053,8 @@ folly::Future<folly::Unit> FuseChannel::fuseListXAttr(
std::string buf;
folly::join('\0', attrs, buf);
buf.push_back('\0');
DCHECK(count == buf.size());
XLOG(DBG7) << "LISTXATTR: " << buf;
folly::fbvector<iovec> vec;
vec.reserve(3);
vec.push_back(make_iovec(out));
vec.push_back(make_iovec(buf.data(), buf.size()));
request.sendReply(std::move(vec));
request.sendReply(folly::StringPiece(buf));
}
});
}

View File

@ -0,0 +1,37 @@
#!/usr/bin/env python3
#
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
from .lib import testcase
import os
import subprocess
@testcase.eden_repo_test
class PatchTest:
def populate_repo(self):
self.repo.write_file('hello', 'hola\n')
self.repo.commit('Initial commit.')
def edenfs_logging_settings(self):
return {'eden.strace': 'DBG7', 'eden.fs.fuse': 'DBG7'}
def test_patch(self):
proc = subprocess.Popen(['patch'], cwd=self.mount, stdin=subprocess.PIPE)
stdout, stderr = proc.communicate(b'''
--- hello
+++ hello
@@ -1 +1 @@
-hola
+bye
''')
print(stdout, stderr)
with open(os.path.join(self.mount, 'hello'), 'r') as f:
self.assertEqual('bye\n', f.read())