in component/libfuse/libfuse_handler.go [675:735]
func libfuse_open(path *C.char, fi *C.fuse_file_info_t) C.int {
name := trimFusePath(path)
name = common.NormalizeObjectName(name)
log.Trace("Libfuse::libfuse_open : %s", name)
// TODO: Should this sit behind a user option? What if we change something to support these in the future?
// Mask out SYNC and DIRECT flags since write operation will fail
if fi.flags&C.O_SYNC != 0 || fi.flags&C.__O_DIRECT != 0 {
log.Info("Libfuse::libfuse_open : Reset flags for open %s, fi.flags %X", name, fi.flags)
// Blobfuse2 does not support the SYNC or DIRECT flag. If a user application passes this flag on to blobfuse2
// and we open the file with this flag, subsequent write operations will fail with "Invalid argument" error.
// Mask them out here in the open call so that write works.
// Oracle RMAN is one such application that sends these flags during backup
fi.flags = fi.flags &^ C.O_SYNC
fi.flags = fi.flags &^ C.__O_DIRECT
}
if !fuseFS.disableWritebackCache {
if fi.flags&C.O_ACCMODE == C.O_WRONLY || fi.flags&C.O_APPEND != 0 {
if fuseFS.ignoreOpenFlags {
log.Warn("Libfuse::libfuse_open : Flags (%X) not supported to open %s when write back cache is on. Ignoring unsupported flags.", fi.flags, name)
// O_ACCMODE disables both RDONLY, WRONLY and RDWR flags
fi.flags = fi.flags &^ (C.O_APPEND | C.O_ACCMODE)
fi.flags = fi.flags | C.O_RDWR
} else {
log.Err("Libfuse::libfuse_open : Flag (%X) not supported to open %s when write back cache is on. Pass --disable-writeback-cache=true or --ignore-open-flags=true via CLI", fi.flags, name)
return -C.EINVAL
}
}
}
handle, err := fuseFS.NextComponent().OpenFile(
internal.OpenFileOptions{
Name: name,
Flags: int(int(fi.flags) & 0xffffffff),
Mode: fs.FileMode(fuseFS.filePermission),
})
if err != nil {
log.Err("Libfuse::libfuse_open : Failed to open %s [%s]", name, err.Error())
if os.IsNotExist(err) {
return -C.ENOENT
} else if os.IsPermission(err) {
return -C.EACCES
} else {
return -C.EIO
}
}
handlemap.Add(handle)
//fi.fh = C.ulong(uintptr(unsafe.Pointer(handle)))
ret_val := C.allocate_native_file_object(C.ulong(handle.UnixFD), C.ulong(uintptr(unsafe.Pointer(handle))), C.ulong(handle.Size))
if !handle.Cached() {
ret_val.fd = 0
}
log.Trace("Libfuse::libfuse_open : %s, handle %d", name, handle.ID)
fi.fh = C.ulong(uintptr(unsafe.Pointer(ret_val)))
// increment open file handles count
libfuseStatsCollector.UpdateStats(stats_manager.Increment, openHandles, (int64)(1))
return 0
}