func libfuse_open()

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
}