mirror of
https://github.com/xiaoqidun/symfs.git
synced 2026-05-12 09:40:58 +08:00
Compare commits
3 Commits
eeff36d167
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2439762607 | |||
| 93817f7114 | |||
| e174d81262 |
@@ -25,6 +25,7 @@ type SymFS struct {
|
||||
fuse.FileSystemBase
|
||||
root string
|
||||
host *fuse.FileSystemHost
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// NewSymFS 创建 SymFS 实例
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -33,6 +34,38 @@ type FileNotifyInformation struct {
|
||||
FileName [1]uint16
|
||||
}
|
||||
|
||||
// winErrToFuse Windows 错误码到 FUSE POSIX errno 的映射表
|
||||
var winErrToFuse = map[syscall.Errno]int{
|
||||
windows.ERROR_FILE_NOT_FOUND: int(fuse.ENOENT),
|
||||
windows.ERROR_PATH_NOT_FOUND: int(fuse.ENOENT),
|
||||
windows.ERROR_ACCESS_DENIED: int(fuse.EACCES),
|
||||
windows.ERROR_INVALID_HANDLE: int(fuse.EBADF),
|
||||
windows.ERROR_NOT_ENOUGH_MEMORY: int(fuse.ENOMEM),
|
||||
windows.ERROR_OUTOFMEMORY: int(fuse.ENOMEM),
|
||||
windows.ERROR_INVALID_DRIVE: int(fuse.ENOENT),
|
||||
windows.ERROR_NO_MORE_FILES: int(fuse.ENOENT),
|
||||
windows.ERROR_WRITE_PROTECT: int(fuse.EROFS),
|
||||
windows.ERROR_NOT_READY: int(fuse.EIO),
|
||||
windows.ERROR_SHARING_VIOLATION: int(fuse.EBUSY),
|
||||
windows.ERROR_LOCK_VIOLATION: int(fuse.EBUSY),
|
||||
windows.ERROR_HANDLE_EOF: int(fuse.EIO),
|
||||
windows.ERROR_HANDLE_DISK_FULL: int(fuse.ENOSPC),
|
||||
windows.ERROR_NOT_SUPPORTED: int(fuse.ENOSYS),
|
||||
windows.ERROR_INVALID_PARAMETER: int(fuse.EINVAL),
|
||||
windows.ERROR_INSUFFICIENT_BUFFER: int(fuse.EINVAL),
|
||||
windows.ERROR_INVALID_NAME: int(fuse.ENOENT),
|
||||
windows.ERROR_DIR_NOT_EMPTY: int(fuse.ENOTEMPTY),
|
||||
windows.ERROR_ALREADY_EXISTS: int(fuse.EEXIST),
|
||||
windows.ERROR_FILE_EXISTS: int(fuse.EEXIST),
|
||||
windows.ERROR_BROKEN_PIPE: int(fuse.EPIPE),
|
||||
windows.ERROR_DISK_FULL: int(fuse.ENOSPC),
|
||||
windows.ERROR_CALL_NOT_IMPLEMENTED: int(fuse.ENOSYS),
|
||||
windows.ERROR_NEGATIVE_SEEK: int(fuse.EINVAL),
|
||||
windows.ERROR_SEEK_ON_DEVICE: int(fuse.ESPIPE),
|
||||
windows.ERROR_DIRECTORY: int(fuse.ENOTDIR),
|
||||
windows.ERROR_NOT_EMPTY: int(fuse.ENOTEMPTY),
|
||||
}
|
||||
|
||||
// errno 转换错误码
|
||||
// 入参: err 错误对象
|
||||
// 返回: int 错误码
|
||||
@@ -40,19 +73,24 @@ func errno(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
if sysErr, ok := err.(syscall.Errno); ok {
|
||||
return -int(sysErr)
|
||||
var sysErr syscall.Errno
|
||||
if errors.As(err, &sysErr) {
|
||||
if fuseErr, ok := winErrToFuse[sysErr]; ok {
|
||||
return -fuseErr
|
||||
}
|
||||
return -int(fuse.ENOENT)
|
||||
}
|
||||
return -int(fuse.EIO)
|
||||
}
|
||||
|
||||
// Init 初始化文件系统
|
||||
func (s *SymFS) Init() {
|
||||
s.done = make(chan struct{})
|
||||
go s.watch()
|
||||
}
|
||||
|
||||
// Destroy 销毁文件系统
|
||||
func (s *SymFS) Destroy() {
|
||||
close(s.done)
|
||||
}
|
||||
|
||||
// Statfs 获取文件系统统计信息
|
||||
@@ -412,7 +450,7 @@ func (s *SymFS) open(path string, flags int, mode uint32) (int, uint64) {
|
||||
return errno(err), ^uint64(0)
|
||||
}
|
||||
if needTruncate {
|
||||
err := windows.SetEndOfFile(h)
|
||||
err = windows.SetEndOfFile(h)
|
||||
if err != nil {
|
||||
windows.CloseHandle(h)
|
||||
h, err = windows.CreateFile(pathPtr, access, shareMode, nil, windows.TRUNCATE_EXISTING, attrs, 0)
|
||||
@@ -436,16 +474,27 @@ func (s *SymFS) watch() {
|
||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
|
||||
nil,
|
||||
windows.OPEN_EXISTING,
|
||||
windows.FILE_FLAG_BACKUP_SEMANTICS,
|
||||
windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OVERLAPPED,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer windows.CloseHandle(h)
|
||||
event, err := windows.CreateEvent(nil, 0, 0, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer windows.CloseHandle(event)
|
||||
buf := make([]byte, 16384)
|
||||
for {
|
||||
var bytesReturned uint32
|
||||
select {
|
||||
case <-s.done:
|
||||
return
|
||||
default:
|
||||
}
|
||||
var overlapped windows.Overlapped
|
||||
overlapped.HEvent = event
|
||||
err = windows.ReadDirectoryChanges(
|
||||
h,
|
||||
&buf[0],
|
||||
@@ -458,10 +507,27 @@ func (s *SymFS) watch() {
|
||||
windows.FILE_NOTIFY_CHANGE_LAST_WRITE|
|
||||
windows.FILE_NOTIFY_CHANGE_CREATION|
|
||||
windows.FILE_NOTIFY_CHANGE_SECURITY,
|
||||
&bytesReturned,
|
||||
nil,
|
||||
(*windows.Overlapped)(unsafe.Pointer(&overlapped)),
|
||||
0,
|
||||
)
|
||||
if err != nil && err != windows.ERROR_IO_PENDING {
|
||||
return
|
||||
}
|
||||
for {
|
||||
result, _ := windows.WaitForSingleObject(event, 100)
|
||||
if result == uint32(windows.WAIT_OBJECT_0) {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case <-s.done:
|
||||
windows.CancelIo(h)
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
var bytesReturned uint32
|
||||
err = windows.GetOverlappedResult(h, (*windows.Overlapped)(unsafe.Pointer(&overlapped)), &bytesReturned, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user