| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "nacl_io/fusefs/fuse_fs.h" | 5 #include "nacl_io/fusefs/fuse_fs.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 | 12 |
| 13 #include "nacl_io/getdents_helper.h" | 13 #include "nacl_io/getdents_helper.h" |
| 14 #include "nacl_io/kernel_handle.h" | 14 #include "nacl_io/kernel_handle.h" |
| 15 #include "nacl_io/log.h" |
| 15 #include "sdk_util/macros.h" | 16 #include "sdk_util/macros.h" |
| 16 | 17 |
| 17 namespace nacl_io { | 18 namespace nacl_io { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 struct FillDirInfo { | 22 struct FillDirInfo { |
| 22 FillDirInfo(GetDentsHelper* getdents, size_t num_bytes) | 23 FillDirInfo(GetDentsHelper* getdents, size_t num_bytes) |
| 23 : getdents(getdents), num_bytes(num_bytes), wrote_offset(false) {} | 24 : getdents(getdents), num_bytes(num_bytes), wrote_offset(false) {} |
| 24 | 25 |
| 25 GetDentsHelper* getdents; | 26 GetDentsHelper* getdents; |
| 26 size_t num_bytes; | 27 size_t num_bytes; |
| 27 bool wrote_offset; | 28 bool wrote_offset; |
| 28 }; | 29 }; |
| 29 | 30 |
| 30 } // namespace | 31 } // namespace |
| 31 | 32 |
| 32 FuseFs::FuseFs() : fuse_ops_(NULL), fuse_user_data_(NULL) { | 33 FuseFs::FuseFs() : fuse_ops_(NULL), fuse_user_data_(NULL) { |
| 33 } | 34 } |
| 34 | 35 |
| 35 Error FuseFs::Init(const FsInitArgs& args) { | 36 Error FuseFs::Init(const FsInitArgs& args) { |
| 36 Error error = Filesystem::Init(args); | 37 Error error = Filesystem::Init(args); |
| 37 if (error) | 38 if (error) |
| 38 return error; | 39 return error; |
| 39 | 40 |
| 40 fuse_ops_ = args.fuse_ops; | 41 fuse_ops_ = args.fuse_ops; |
| 41 if (fuse_ops_ == NULL) | 42 if (fuse_ops_ == NULL) { |
| 43 LOG_ERROR("fuse_ops_ is NULL."); |
| 42 return EINVAL; | 44 return EINVAL; |
| 45 } |
| 43 | 46 |
| 44 if (fuse_ops_->init) { | 47 if (fuse_ops_->init) { |
| 45 struct fuse_conn_info info; | 48 struct fuse_conn_info info; |
| 46 fuse_user_data_ = fuse_ops_->init(&info); | 49 fuse_user_data_ = fuse_ops_->init(&info); |
| 47 } | 50 } |
| 48 | 51 |
| 49 return 0; | 52 return 0; |
| 50 } | 53 } |
| 51 | 54 |
| 52 void FuseFs::Destroy() { | 55 void FuseFs::Destroy() { |
| 53 if (fuse_ops_ && fuse_ops_->destroy) | 56 if (fuse_ops_ && fuse_ops_->destroy) |
| 54 fuse_ops_->destroy(fuse_user_data_); | 57 fuse_ops_->destroy(fuse_user_data_); |
| 55 } | 58 } |
| 56 | 59 |
| 57 Error FuseFs::Access(const Path& path, int a_mode) { | 60 Error FuseFs::Access(const Path& path, int a_mode) { |
| 58 if (!fuse_ops_->access) | 61 if (!fuse_ops_->access) { |
| 62 LOG_TRACE("fuse_ops_->access is NULL."); |
| 59 return ENOSYS; | 63 return ENOSYS; |
| 64 } |
| 60 | 65 |
| 61 int result = fuse_ops_->access(path.Join().c_str(), a_mode); | 66 int result = fuse_ops_->access(path.Join().c_str(), a_mode); |
| 62 if (result < 0) | 67 if (result < 0) |
| 63 return -result; | 68 return -result; |
| 64 | 69 |
| 65 return 0; | 70 return 0; |
| 66 } | 71 } |
| 67 | 72 |
| 68 Error FuseFs::Open(const Path& path, int open_flags, ScopedNode* out_node) { | 73 Error FuseFs::Open(const Path& path, int open_flags, ScopedNode* out_node) { |
| 69 std::string path_str = path.Join(); | 74 std::string path_str = path.Join(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 80 mode_t mode = S_IRALL | S_IWALL; | 85 mode_t mode = S_IRALL | S_IWALL; |
| 81 if (fuse_ops_->create) { | 86 if (fuse_ops_->create) { |
| 82 result = fuse_ops_->create(path_cstr, mode, &fi); | 87 result = fuse_ops_->create(path_cstr, mode, &fi); |
| 83 if (result < 0) | 88 if (result < 0) |
| 84 return -result; | 89 return -result; |
| 85 } else if (fuse_ops_->mknod) { | 90 } else if (fuse_ops_->mknod) { |
| 86 result = fuse_ops_->mknod(path_cstr, mode, dev_); | 91 result = fuse_ops_->mknod(path_cstr, mode, dev_); |
| 87 if (result < 0) | 92 if (result < 0) |
| 88 return -result; | 93 return -result; |
| 89 } else { | 94 } else { |
| 95 LOG_TRACE("fuse_ops_->create and fuse_ops_->mknod are NULL."); |
| 90 return ENOSYS; | 96 return ENOSYS; |
| 91 } | 97 } |
| 92 } else { | 98 } else { |
| 93 // First determine if this is a regular file or a directory. | 99 // First determine if this is a regular file or a directory. |
| 94 if (fuse_ops_->getattr) { | 100 if (fuse_ops_->getattr) { |
| 95 struct stat statbuf; | 101 struct stat statbuf; |
| 96 result = fuse_ops_->getattr(path_cstr, &statbuf); | 102 result = fuse_ops_->getattr(path_cstr, &statbuf); |
| 97 if (result < 0) | 103 if (result < 0) |
| 98 return -result; | 104 return -result; |
| 99 | 105 |
| 100 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { | 106 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { |
| 101 // This is a directory. Don't try to open, just create a new node with | 107 // This is a directory. Don't try to open, just create a new node with |
| 102 // this path. | 108 // this path. |
| 103 ScopedNode node(new DirFuseFsNode(this, fuse_ops_, fi, path_cstr)); | 109 ScopedNode node(new DirFuseFsNode(this, fuse_ops_, fi, path_cstr)); |
| 104 Error error = node->Init(open_flags); | 110 Error error = node->Init(open_flags); |
| 105 if (error) | 111 if (error) |
| 106 return error; | 112 return error; |
| 107 | 113 |
| 108 *out_node = node; | 114 *out_node = node; |
| 109 return 0; | 115 return 0; |
| 110 } | 116 } |
| 111 } | 117 } |
| 112 | 118 |
| 113 // Existing file. | 119 // Existing file. |
| 114 if (open_flags & O_TRUNC) { | 120 if (open_flags & O_TRUNC) { |
| 115 // According to the FUSE docs, O_TRUNC does two calls: first truncate() | 121 // According to the FUSE docs, O_TRUNC does two calls: first truncate() |
| 116 // then open(). | 122 // then open(). |
| 117 if (!fuse_ops_->truncate) | 123 if (!fuse_ops_->truncate) { |
| 124 LOG_TRACE("fuse_ops_->truncate is NULL."); |
| 118 return ENOSYS; | 125 return ENOSYS; |
| 126 } |
| 119 result = fuse_ops_->truncate(path_cstr, 0); | 127 result = fuse_ops_->truncate(path_cstr, 0); |
| 120 if (result < 0) | 128 if (result < 0) |
| 121 return -result; | 129 return -result; |
| 122 } | 130 } |
| 123 | 131 |
| 124 if (!fuse_ops_->open) | 132 if (!fuse_ops_->open) { |
| 133 LOG_TRACE("fuse_ops_->open is NULL."); |
| 125 return ENOSYS; | 134 return ENOSYS; |
| 135 } |
| 126 result = fuse_ops_->open(path_cstr, &fi); | 136 result = fuse_ops_->open(path_cstr, &fi); |
| 127 if (result < 0) | 137 if (result < 0) |
| 128 return -result; | 138 return -result; |
| 129 } | 139 } |
| 130 | 140 |
| 131 ScopedNode node(new FileFuseFsNode(this, fuse_ops_, fi, path_cstr)); | 141 ScopedNode node(new FileFuseFsNode(this, fuse_ops_, fi, path_cstr)); |
| 132 Error error = node->Init(open_flags); | 142 Error error = node->Init(open_flags); |
| 133 if (error) | 143 if (error) |
| 134 return error; | 144 return error; |
| 135 | 145 |
| 136 *out_node = node; | 146 *out_node = node; |
| 137 return 0; | 147 return 0; |
| 138 } | 148 } |
| 139 | 149 |
| 140 Error FuseFs::Unlink(const Path& path) { | 150 Error FuseFs::Unlink(const Path& path) { |
| 141 if (!fuse_ops_->unlink) | 151 if (!fuse_ops_->unlink) { |
| 152 LOG_TRACE("fuse_ops_->unlink is NULL."); |
| 142 return ENOSYS; | 153 return ENOSYS; |
| 154 } |
| 143 | 155 |
| 144 int result = fuse_ops_->unlink(path.Join().c_str()); | 156 int result = fuse_ops_->unlink(path.Join().c_str()); |
| 145 if (result < 0) | 157 if (result < 0) |
| 146 return -result; | 158 return -result; |
| 147 | 159 |
| 148 return 0; | 160 return 0; |
| 149 } | 161 } |
| 150 | 162 |
| 151 Error FuseFs::Mkdir(const Path& path, int perm) { | 163 Error FuseFs::Mkdir(const Path& path, int perm) { |
| 152 if (!fuse_ops_->mkdir) | 164 if (!fuse_ops_->mkdir) { |
| 165 LOG_TRACE("fuse_ops_->mkdir is NULL."); |
| 153 return ENOSYS; | 166 return ENOSYS; |
| 167 } |
| 154 | 168 |
| 155 int result = fuse_ops_->mkdir(path.Join().c_str(), perm); | 169 int result = fuse_ops_->mkdir(path.Join().c_str(), perm); |
| 156 if (result < 0) | 170 if (result < 0) |
| 157 return -result; | 171 return -result; |
| 158 | 172 |
| 159 return 0; | 173 return 0; |
| 160 } | 174 } |
| 161 | 175 |
| 162 Error FuseFs::Rmdir(const Path& path) { | 176 Error FuseFs::Rmdir(const Path& path) { |
| 163 if (!fuse_ops_->rmdir) | 177 if (!fuse_ops_->rmdir) { |
| 178 LOG_TRACE("fuse_ops_->rmdir is NULL."); |
| 164 return ENOSYS; | 179 return ENOSYS; |
| 180 } |
| 165 | 181 |
| 166 int result = fuse_ops_->rmdir(path.Join().c_str()); | 182 int result = fuse_ops_->rmdir(path.Join().c_str()); |
| 167 if (result < 0) | 183 if (result < 0) |
| 168 return -result; | 184 return -result; |
| 169 | 185 |
| 170 return 0; | 186 return 0; |
| 171 } | 187 } |
| 172 | 188 |
| 173 Error FuseFs::Remove(const Path& path) { | 189 Error FuseFs::Remove(const Path& path) { |
| 174 ScopedNode node; | 190 ScopedNode node; |
| 175 Error error = Open(path, O_RDONLY, &node); | 191 Error error = Open(path, O_RDONLY, &node); |
| 176 if (error) | 192 if (error) |
| 177 return error; | 193 return error; |
| 178 | 194 |
| 179 struct stat statbuf; | 195 struct stat statbuf; |
| 180 error = node->GetStat(&statbuf); | 196 error = node->GetStat(&statbuf); |
| 181 if (error) | 197 if (error) |
| 182 return error; | 198 return error; |
| 183 | 199 |
| 184 node.reset(); | 200 node.reset(); |
| 185 | 201 |
| 186 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { | 202 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { |
| 187 return Rmdir(path); | 203 return Rmdir(path); |
| 188 } else { | 204 } else { |
| 189 return Unlink(path); | 205 return Unlink(path); |
| 190 } | 206 } |
| 191 } | 207 } |
| 192 | 208 |
| 193 Error FuseFs::Rename(const Path& path, const Path& newpath) { | 209 Error FuseFs::Rename(const Path& path, const Path& newpath) { |
| 194 if (!fuse_ops_->rename) | 210 if (!fuse_ops_->rename) { |
| 211 LOG_TRACE("fuse_ops_->rename is NULL."); |
| 195 return ENOSYS; | 212 return ENOSYS; |
| 213 } |
| 196 | 214 |
| 197 int result = fuse_ops_->rename(path.Join().c_str(), newpath.Join().c_str()); | 215 int result = fuse_ops_->rename(path.Join().c_str(), newpath.Join().c_str()); |
| 198 if (result < 0) | 216 if (result < 0) |
| 199 return -result; | 217 return -result; |
| 200 | 218 |
| 201 return 0; | 219 return 0; |
| 202 } | 220 } |
| 203 | 221 |
| 204 FuseFsNode::FuseFsNode(Filesystem* filesystem, | 222 FuseFsNode::FuseFsNode(Filesystem* filesystem, |
| 205 struct fuse_operations* fuse_ops, | 223 struct fuse_operations* fuse_ops, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 223 int result; | 241 int result; |
| 224 if (fuse_ops_->fgetattr) { | 242 if (fuse_ops_->fgetattr) { |
| 225 result = fuse_ops_->fgetattr(path_.c_str(), stat, &info_); | 243 result = fuse_ops_->fgetattr(path_.c_str(), stat, &info_); |
| 226 if (result < 0) | 244 if (result < 0) |
| 227 return -result; | 245 return -result; |
| 228 } else if (fuse_ops_->getattr) { | 246 } else if (fuse_ops_->getattr) { |
| 229 result = fuse_ops_->getattr(path_.c_str(), stat); | 247 result = fuse_ops_->getattr(path_.c_str(), stat); |
| 230 if (result < 0) | 248 if (result < 0) |
| 231 return -result; | 249 return -result; |
| 232 } else { | 250 } else { |
| 251 LOG_TRACE("fuse_ops_->fgetattr and fuse_ops_->getattr are NULL."); |
| 233 return ENOSYS; | 252 return ENOSYS; |
| 234 } | 253 } |
| 235 | 254 |
| 236 // Also update the cached stat values. | 255 // Also update the cached stat values. |
| 237 stat_ = *stat; | 256 stat_ = *stat; |
| 238 return 0; | 257 return 0; |
| 239 } | 258 } |
| 240 | 259 |
| 241 Error FuseFsNode::VIoctl(int request, va_list args) { | 260 Error FuseFsNode::VIoctl(int request, va_list args) { |
| 242 // TODO(binji): implement | 261 LOG_ERROR("Ioctl not implemented for fusefs."); |
| 243 return ENOSYS; | 262 return ENOSYS; |
| 244 } | 263 } |
| 245 | 264 |
| 246 Error FuseFsNode::Tcflush(int queue_selector) { | 265 Error FuseFsNode::Tcflush(int queue_selector) { |
| 247 // TODO(binji): use ioctl for this? | 266 LOG_ERROR("Tcflush not implemented for fusefs."); |
| 248 return ENOSYS; | 267 return ENOSYS; |
| 249 } | 268 } |
| 250 | 269 |
| 251 Error FuseFsNode::Tcgetattr(struct termios* termios_p) { | 270 Error FuseFsNode::Tcgetattr(struct termios* termios_p) { |
| 252 // TODO(binji): use ioctl for this? | 271 LOG_ERROR("Tcgetattr not implemented for fusefs."); |
| 253 return ENOSYS; | 272 return ENOSYS; |
| 254 } | 273 } |
| 255 | 274 |
| 256 Error FuseFsNode::Tcsetattr(int optional_actions, | 275 Error FuseFsNode::Tcsetattr(int optional_actions, |
| 257 const struct termios* termios_p) { | 276 const struct termios* termios_p) { |
| 258 // TODO(binji): use ioctl for this? | 277 LOG_ERROR("Tcsetattr not implemented for fusefs."); |
| 259 return ENOSYS; | 278 return ENOSYS; |
| 260 } | 279 } |
| 261 | 280 |
| 262 Error FuseFsNode::GetSize(off_t* out_size) { | 281 Error FuseFsNode::GetSize(off_t* out_size) { |
| 263 struct stat statbuf; | 282 struct stat statbuf; |
| 264 Error error = GetStat(&statbuf); | 283 Error error = GetStat(&statbuf); |
| 265 if (error) | 284 if (error) |
| 266 return error; | 285 return error; |
| 267 | 286 |
| 268 *out_size = stat_.st_size; | 287 *out_size = stat_.st_size; |
| 269 return 0; | 288 return 0; |
| 270 } | 289 } |
| 271 | 290 |
| 272 FileFuseFsNode::FileFuseFsNode(Filesystem* filesystem, | 291 FileFuseFsNode::FileFuseFsNode(Filesystem* filesystem, |
| 273 struct fuse_operations* fuse_ops, | 292 struct fuse_operations* fuse_ops, |
| 274 struct fuse_file_info& info, | 293 struct fuse_file_info& info, |
| 275 const std::string& path) | 294 const std::string& path) |
| 276 : FuseFsNode(filesystem, fuse_ops, info, path) { | 295 : FuseFsNode(filesystem, fuse_ops, info, path) { |
| 277 } | 296 } |
| 278 | 297 |
| 279 void FileFuseFsNode::Destroy() { | 298 void FileFuseFsNode::Destroy() { |
| 280 if (!fuse_ops_->release) | 299 if (!fuse_ops_->release) |
| 281 return; | 300 return; |
| 282 fuse_ops_->release(path_.c_str(), &info_); | 301 fuse_ops_->release(path_.c_str(), &info_); |
| 283 } | 302 } |
| 284 | 303 |
| 285 Error FileFuseFsNode::FSync() { | 304 Error FileFuseFsNode::FSync() { |
| 286 if (!fuse_ops_->fsync) | 305 if (!fuse_ops_->fsync) { |
| 306 LOG_ERROR("fuse_ops_->fsync is NULL."); |
| 287 return ENOSYS; | 307 return ENOSYS; |
| 308 } |
| 288 | 309 |
| 289 int datasync = 0; | 310 int datasync = 0; |
| 290 int result = fuse_ops_->fsync(path_.c_str(), datasync, &info_); | 311 int result = fuse_ops_->fsync(path_.c_str(), datasync, &info_); |
| 291 if (result < 0) | 312 if (result < 0) |
| 292 return -result; | 313 return -result; |
| 293 return 0; | 314 return 0; |
| 294 } | 315 } |
| 295 | 316 |
| 296 Error FileFuseFsNode::FTruncate(off_t length) { | 317 Error FileFuseFsNode::FTruncate(off_t length) { |
| 297 if (!fuse_ops_->ftruncate) | 318 if (!fuse_ops_->ftruncate) { |
| 319 LOG_ERROR("fuse_ops_->ftruncate is NULL."); |
| 298 return ENOSYS; | 320 return ENOSYS; |
| 321 } |
| 299 | 322 |
| 300 int result = fuse_ops_->ftruncate(path_.c_str(), length, &info_); | 323 int result = fuse_ops_->ftruncate(path_.c_str(), length, &info_); |
| 301 if (result < 0) | 324 if (result < 0) |
| 302 return -result; | 325 return -result; |
| 303 return 0; | 326 return 0; |
| 304 } | 327 } |
| 305 | 328 |
| 306 Error FileFuseFsNode::Read(const HandleAttr& attr, | 329 Error FileFuseFsNode::Read(const HandleAttr& attr, |
| 307 void* buf, | 330 void* buf, |
| 308 size_t count, | 331 size_t count, |
| 309 int* out_bytes) { | 332 int* out_bytes) { |
| 310 if (!fuse_ops_->read) | 333 if (!fuse_ops_->read) { |
| 334 LOG_ERROR("fuse_ops_->read is NULL."); |
| 311 return ENOSYS; | 335 return ENOSYS; |
| 336 } |
| 312 | 337 |
| 313 char* cbuf = static_cast<char*>(buf); | 338 char* cbuf = static_cast<char*>(buf); |
| 314 | 339 |
| 315 int result = fuse_ops_->read(path_.c_str(), cbuf, count, attr.offs, &info_); | 340 int result = fuse_ops_->read(path_.c_str(), cbuf, count, attr.offs, &info_); |
| 316 if (result < 0) | 341 if (result < 0) |
| 317 return -result; | 342 return -result; |
| 318 | 343 |
| 319 // Fuse docs say that a read() call will always completely fill the buffer | 344 // Fuse docs say that a read() call will always completely fill the buffer |
| 320 // (padding with zeroes) unless the direct_io filesystem flag is set. | 345 // (padding with zeroes) unless the direct_io filesystem flag is set. |
| 321 // TODO(binji): support the direct_io flag | 346 // TODO(binji): support the direct_io flag |
| 322 if (static_cast<size_t>(result) < count) | 347 if (static_cast<size_t>(result) < count) |
| 323 memset(&cbuf[result], 0, count - result); | 348 memset(&cbuf[result], 0, count - result); |
| 324 | 349 |
| 325 *out_bytes = count; | 350 *out_bytes = count; |
| 326 return 0; | 351 return 0; |
| 327 } | 352 } |
| 328 | 353 |
| 329 Error FileFuseFsNode::Write(const HandleAttr& attr, | 354 Error FileFuseFsNode::Write(const HandleAttr& attr, |
| 330 const void* buf, | 355 const void* buf, |
| 331 size_t count, | 356 size_t count, |
| 332 int* out_bytes) { | 357 int* out_bytes) { |
| 333 if (!fuse_ops_->write) | 358 if (!fuse_ops_->write) { |
| 359 LOG_ERROR("fuse_ops_->write is NULL."); |
| 334 return ENOSYS; | 360 return ENOSYS; |
| 361 } |
| 335 | 362 |
| 336 int result = fuse_ops_->write( | 363 int result = fuse_ops_->write( |
| 337 path_.c_str(), static_cast<const char*>(buf), count, attr.offs, &info_); | 364 path_.c_str(), static_cast<const char*>(buf), count, attr.offs, &info_); |
| 338 if (result < 0) | 365 if (result < 0) |
| 339 return -result; | 366 return -result; |
| 340 | 367 |
| 341 // Fuse docs say that a write() call will always write the entire buffer | 368 // Fuse docs say that a write() call will always write the entire buffer |
| 342 // unless the direct_io filesystem flag is set. | 369 // unless the direct_io filesystem flag is set. |
| 343 // TODO(binji): What should we do if the user breaks this contract? Warn? | 370 // TODO(binji): What should we do if the user breaks this contract? Warn? |
| 344 // TODO(binji): support the direct_io flag | 371 // TODO(binji): support the direct_io flag |
| 345 *out_bytes = result; | 372 *out_bytes = result; |
| 346 return 0; | 373 return 0; |
| 347 } | 374 } |
| 348 | 375 |
| 349 DirFuseFsNode::DirFuseFsNode(Filesystem* filesystem, | 376 DirFuseFsNode::DirFuseFsNode(Filesystem* filesystem, |
| 350 struct fuse_operations* fuse_ops, | 377 struct fuse_operations* fuse_ops, |
| 351 struct fuse_file_info& info, | 378 struct fuse_file_info& info, |
| 352 const std::string& path) | 379 const std::string& path) |
| 353 : FuseFsNode(filesystem, fuse_ops, info, path) { | 380 : FuseFsNode(filesystem, fuse_ops, info, path) { |
| 354 } | 381 } |
| 355 | 382 |
| 356 void DirFuseFsNode::Destroy() { | 383 void DirFuseFsNode::Destroy() { |
| 357 if (!fuse_ops_->releasedir) | 384 if (!fuse_ops_->releasedir) |
| 358 return; | 385 return; |
| 359 fuse_ops_->releasedir(path_.c_str(), &info_); | 386 fuse_ops_->releasedir(path_.c_str(), &info_); |
| 360 } | 387 } |
| 361 | 388 |
| 362 Error DirFuseFsNode::FSync() { | 389 Error DirFuseFsNode::FSync() { |
| 363 if (!fuse_ops_->fsyncdir) | 390 if (!fuse_ops_->fsyncdir) { |
| 391 LOG_ERROR("fuse_ops_->fsyncdir is NULL."); |
| 364 return ENOSYS; | 392 return ENOSYS; |
| 393 } |
| 365 | 394 |
| 366 int datasync = 0; | 395 int datasync = 0; |
| 367 int result = fuse_ops_->fsyncdir(path_.c_str(), datasync, &info_); | 396 int result = fuse_ops_->fsyncdir(path_.c_str(), datasync, &info_); |
| 368 if (result < 0) | 397 if (result < 0) |
| 369 return -result; | 398 return -result; |
| 370 return 0; | 399 return 0; |
| 371 } | 400 } |
| 372 | 401 |
| 373 Error DirFuseFsNode::GetDents(size_t offs, | 402 Error DirFuseFsNode::GetDents(size_t offs, |
| 374 struct dirent* pdir, | 403 struct dirent* pdir, |
| 375 size_t count, | 404 size_t count, |
| 376 int* out_bytes) { | 405 int* out_bytes) { |
| 377 if (!fuse_ops_->readdir) | 406 if (!fuse_ops_->readdir) { |
| 407 LOG_ERROR("fuse_ops_->readdir is NULL."); |
| 378 return ENOSYS; | 408 return ENOSYS; |
| 409 } |
| 379 | 410 |
| 380 bool opened_dir = false; | 411 bool opened_dir = false; |
| 381 int result; | 412 int result; |
| 382 | 413 |
| 383 // Opendir is not necessary, only readdir. Call it anyway, if it is defined. | 414 // Opendir is not necessary, only readdir. Call it anyway, if it is defined. |
| 384 if (fuse_ops_->opendir) { | 415 if (fuse_ops_->opendir) { |
| 385 result = fuse_ops_->opendir(path_.c_str(), &info_); | 416 result = fuse_ops_->opendir(path_.c_str(), &info_); |
| 386 if (result < 0) | 417 if (result < 0) |
| 387 return -result; | 418 return -result; |
| 388 | 419 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 } else { | 477 } else { |
| 447 fill_info->getdents->AddDirent(ino, name, strlen(name)); | 478 fill_info->getdents->AddDirent(ino, name, strlen(name)); |
| 448 fill_info->num_bytes -= sizeof(dirent); | 479 fill_info->num_bytes -= sizeof(dirent); |
| 449 // According to the docs, we can never return 1 (buffer full) when the | 480 // According to the docs, we can never return 1 (buffer full) when the |
| 450 // offset is zero (the user is probably ignoring the result anyway). | 481 // offset is zero (the user is probably ignoring the result anyway). |
| 451 return 0; | 482 return 0; |
| 452 } | 483 } |
| 453 } | 484 } |
| 454 | 485 |
| 455 } // namespace nacl_io | 486 } // namespace nacl_io |
| OLD | NEW |