1/* 2 * fsop.go 3 * 4 * Copyright 2017-2020 Bill Zissimopoulos 5 */ 6/* 7 * This file is part of Cgofuse. 8 * 9 * It is licensed under the MIT license. The full license text can be found 10 * in the License.txt file at the root of this project. 11 */ 12 13// Package fuse allows the creation of user mode file systems in Go. 14// 15// A user mode file system is a user mode process that receives file system operations 16// from the OS FUSE layer and satisfies them in user mode. A user mode file system 17// implements the interface FileSystemInterface either directly or by embedding a 18// FileSystemBase struct which provides a default (empty) implementation of all methods 19// in FileSystemInterface. 20// 21// In order to expose the user mode file system to the OS, the file system must be hosted 22// (mounted) by a FileSystemHost. The FileSystemHost Mount() method is used for this 23// purpose. 24// 25// A note on thread-safety: In general FUSE file systems are expected to protect their 26// own data structures. Many FUSE implementations provide a -s command line option that 27// when used, it instructs the FUSE implementation to serialize requests. This option 28// can be passed to the FileSystemHost Mount() method, when the file system is mounted. 29package fuse 30 31import ( 32 "strconv" 33 "sync" 34 "time" 35) 36 37// Timespec contains a time as the UNIX time in seconds and nanoseconds. 38// This structure is analogous to the POSIX struct timespec. 39type Timespec struct { 40 Sec int64 41 Nsec int64 42} 43 44// NewTimespec creates a Timespec from a time.Time. 45func NewTimespec(t time.Time) Timespec { 46 return Timespec{t.Unix(), int64(t.Nanosecond())} 47} 48 49// Now creates a Timespec that contains the current time. 50func Now() Timespec { 51 return NewTimespec(time.Now()) 52} 53 54// Time returns the Timespec as a time.Time. 55func (ts *Timespec) Time() time.Time { 56 return time.Unix(ts.Sec, ts.Nsec) 57} 58 59// Statfs_t contains file system information. 60// This structure is analogous to the POSIX struct statvfs (NOT struct statfs). 61// Not all fields are honored by all FUSE implementations. 62type Statfs_t struct { 63 // File system block size. 64 Bsize uint64 65 66 // Fundamental file system block size. 67 Frsize uint64 68 69 // Total number of blocks on file system in units of Frsize. 70 Blocks uint64 71 72 // Total number of free blocks. 73 Bfree uint64 74 75 // Number of free blocks available to non-privileged process. 76 Bavail uint64 77 78 // Total number of file serial numbers. 79 Files uint64 80 81 // Total number of free file serial numbers. 82 Ffree uint64 83 84 // Number of file serial numbers available to non-privileged process. 85 Favail uint64 86 87 // File system ID. [IGNORED] 88 Fsid uint64 89 90 // Bit mask of Flag values. [IGNORED] 91 Flag uint64 92 93 // Maximum filename length. 94 Namemax uint64 95} 96 97// Stat_t contains file metadata information. 98// This structure is analogous to the POSIX struct stat. 99// Not all fields are honored by all FUSE implementations. 100type Stat_t struct { 101 // Device ID of device containing file. [IGNORED] 102 Dev uint64 103 104 // File serial number. [IGNORED unless the use_ino mount option is given.] 105 Ino uint64 106 107 // Mode of file. 108 Mode uint32 109 110 // Number of hard links to the file. 111 Nlink uint32 112 113 // User ID of file. 114 Uid uint32 115 116 // Group ID of file. 117 Gid uint32 118 119 // Device ID (if file is character or block special). 120 Rdev uint64 121 122 // For regular files, the file size in bytes. 123 // For symbolic links, the length in bytes of the 124 // pathname contained in the symbolic link. 125 Size int64 126 127 // Last data access timestamp. 128 Atim Timespec 129 130 // Last data modification timestamp. 131 Mtim Timespec 132 133 // Last file status change timestamp. 134 Ctim Timespec 135 136 // A file system-specific preferred I/O block size for this object. 137 Blksize int64 138 139 // Number of blocks allocated for this object. 140 Blocks int64 141 142 // File creation (birth) timestamp. [OSX and Windows only] 143 Birthtim Timespec 144 145 // BSD flags (UF_*). [OSX and Windows only] 146 Flags uint32 147} 148 149// FileInfo_t contains open file information. 150// This structure is analogous to the FUSE struct fuse_file_info. 151type FileInfo_t struct { 152 // Open flags: a combination of the fuse.O_* constants. 153 Flags int 154 155 // Use direct I/O on this file. [IGNORED on Windows] 156 DirectIo bool 157 158 // Do not invalidate file cache. [IGNORED on Windows] 159 KeepCache bool 160 161 // File is not seekable. [IGNORED on Windows] 162 NonSeekable bool 163 164 // File handle. 165 Fh uint64 166} 167 168/* 169// Lock_t contains file locking information. 170// This structure is analogous to the POSIX struct flock. 171type Lock_t struct { 172 // Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. 173 Type int16 174 175 // Flag for starting offset. 176 Whence int16 177 178 // Relative offset in bytes. 179 Start int64 180 181 // Size; if 0 then until EOF. 182 Len int64 183 184 // Process ID of the process holding the lock 185 Pid int 186} 187*/ 188 189// FileSystemInterface is the interface that a user mode file system must implement. 190// 191// The file system will receive an Init() call when the file system is created; 192// the Init() call will happen prior to receiving any other file system calls. 193// Note that there are no guarantees on the exact timing of when Init() is called. 194// For example, it cannot be assumed that the file system is mounted at the time 195// the Init() call is received. 196// 197// The file system will receive a Destroy() call when the file system is destroyed; 198// the Destroy() call will always be the last call to be received by the file system. 199// Note that depending on how the file system is terminated the file system may not 200// receive the Destroy() call. For example, it will not receive the Destroy() call 201// if the file system process is forcibly killed. 202// 203// Except for Init() and Destroy() all file system operations must return 0 on success 204// or a FUSE error on failure. To return an error return the NEGATIVE value of a 205// particular error. For example, to report "file not found" return -fuse.ENOENT. 206type FileSystemInterface interface { 207 // Init is called when the file system is created. 208 Init() 209 210 // Destroy is called when the file system is destroyed. 211 Destroy() 212 213 // Statfs gets file system statistics. 214 Statfs(path string, stat *Statfs_t) int 215 216 // Mknod creates a file node. 217 Mknod(path string, mode uint32, dev uint64) int 218 219 // Mkdir creates a directory. 220 Mkdir(path string, mode uint32) int 221 222 // Unlink removes a file. 223 Unlink(path string) int 224 225 // Rmdir removes a directory. 226 Rmdir(path string) int 227 228 // Link creates a hard link to a file. 229 Link(oldpath string, newpath string) int 230 231 // Symlink creates a symbolic link. 232 Symlink(target string, newpath string) int 233 234 // Readlink reads the target of a symbolic link. 235 Readlink(path string) (int, string) 236 237 // Rename renames a file. 238 Rename(oldpath string, newpath string) int 239 240 // Chmod changes the permission bits of a file. 241 Chmod(path string, mode uint32) int 242 243 // Chown changes the owner and group of a file. 244 Chown(path string, uid uint32, gid uint32) int 245 246 // Utimens changes the access and modification times of a file. 247 Utimens(path string, tmsp []Timespec) int 248 249 // Access checks file access permissions. 250 Access(path string, mask uint32) int 251 252 // Create creates and opens a file. 253 // The flags are a combination of the fuse.O_* constants. 254 Create(path string, flags int, mode uint32) (int, uint64) 255 256 // Open opens a file. 257 // The flags are a combination of the fuse.O_* constants. 258 Open(path string, flags int) (int, uint64) 259 260 // Getattr gets file attributes. 261 Getattr(path string, stat *Stat_t, fh uint64) int 262 263 // Truncate changes the size of a file. 264 Truncate(path string, size int64, fh uint64) int 265 266 // Read reads data from a file. 267 Read(path string, buff []byte, ofst int64, fh uint64) int 268 269 // Write writes data to a file. 270 Write(path string, buff []byte, ofst int64, fh uint64) int 271 272 // Flush flushes cached file data. 273 Flush(path string, fh uint64) int 274 275 // Release closes an open file. 276 Release(path string, fh uint64) int 277 278 // Fsync synchronizes file contents. 279 Fsync(path string, datasync bool, fh uint64) int 280 281 // Lock performs a file locking operation. 282 //Lock(path string, cmd int, lock *Lock_t, fh uint64) int 283 284 // Opendir opens a directory. 285 Opendir(path string) (int, uint64) 286 287 // Readdir reads a directory. 288 Readdir(path string, 289 fill func(name string, stat *Stat_t, ofst int64) bool, 290 ofst int64, 291 fh uint64) int 292 293 // Releasedir closes an open directory. 294 Releasedir(path string, fh uint64) int 295 296 // Fsyncdir synchronizes directory contents. 297 Fsyncdir(path string, datasync bool, fh uint64) int 298 299 // Setxattr sets extended attributes. 300 Setxattr(path string, name string, value []byte, flags int) int 301 302 // Getxattr gets extended attributes. 303 Getxattr(path string, name string) (int, []byte) 304 305 // Removexattr removes extended attributes. 306 Removexattr(path string, name string) int 307 308 // Listxattr lists extended attributes. 309 Listxattr(path string, fill func(name string) bool) int 310} 311 312// FileSystemOpenEx is the interface that wraps the OpenEx and CreateEx methods. 313// 314// OpenEx and CreateEx are similar to Open and Create except that they allow 315// direct manipulation of the FileInfo_t struct (which is analogous to the 316// FUSE struct fuse_file_info). 317type FileSystemOpenEx interface { 318 CreateEx(path string, mode uint32, fi *FileInfo_t) int 319 OpenEx(path string, fi *FileInfo_t) int 320} 321 322// FileSystemChflags is the interface that wraps the Chflags method. 323// 324// Chflags changes the BSD file flags (Windows file attributes). [OSX and Windows only] 325type FileSystemChflags interface { 326 Chflags(path string, flags uint32) int 327} 328 329// FileSystemSetcrtime is the interface that wraps the Setcrtime method. 330// 331// Setcrtime changes the file creation (birth) time. [OSX and Windows only] 332type FileSystemSetcrtime interface { 333 Setcrtime(path string, tmsp Timespec) int 334} 335 336// FileSystemSetchgtime is the interface that wraps the Setchgtime method. 337// 338// Setchgtime changes the file change (ctime) time. [OSX and Windows only] 339type FileSystemSetchgtime interface { 340 Setchgtime(path string, tmsp Timespec) int 341} 342 343// Error encapsulates a FUSE error code. In some rare circumstances it is useful 344// to signal an error to the FUSE layer by boxing the error code using Error and 345// calling panic(). The FUSE layer will recover and report the boxed error code 346// to the OS. 347type Error int 348 349var errorStringMap map[Error]string 350var errorStringOnce sync.Once 351 352func (self Error) Error() string { 353 errorStringOnce.Do(func() { 354 errorStringMap = make(map[Error]string) 355 for _, i := range errorStrings { 356 errorStringMap[Error(-i.errc)] = i.errs 357 } 358 }) 359 360 if 0 <= self { 361 return strconv.Itoa(int(self)) 362 } else { 363 if errs, ok := errorStringMap[self]; ok { 364 return "-fuse." + errs 365 } 366 return "fuse.Error(" + strconv.Itoa(int(self)) + ")" 367 } 368} 369 370func (self Error) String() string { 371 return self.Error() 372} 373 374func (self Error) GoString() string { 375 return self.Error() 376} 377 378var _ error = (*Error)(nil) 379 380// FileSystemBase provides default implementations of the methods in FileSystemInterface. 381// The default implementations are either empty or return -ENOSYS to signal that the 382// file system does not implement a particular operation to the FUSE layer. 383type FileSystemBase struct { 384} 385 386// Init is called when the file system is created. 387// The FileSystemBase implementation does nothing. 388func (*FileSystemBase) Init() { 389} 390 391// Destroy is called when the file system is destroyed. 392// The FileSystemBase implementation does nothing. 393func (*FileSystemBase) Destroy() { 394} 395 396// Statfs gets file system statistics. 397// The FileSystemBase implementation returns -ENOSYS. 398func (*FileSystemBase) Statfs(path string, stat *Statfs_t) int { 399 return -ENOSYS 400} 401 402// Mknod creates a file node. 403// The FileSystemBase implementation returns -ENOSYS. 404func (*FileSystemBase) Mknod(path string, mode uint32, dev uint64) int { 405 return -ENOSYS 406} 407 408// Mkdir creates a directory. 409// The FileSystemBase implementation returns -ENOSYS. 410func (*FileSystemBase) Mkdir(path string, mode uint32) int { 411 return -ENOSYS 412} 413 414// Unlink removes a file. 415// The FileSystemBase implementation returns -ENOSYS. 416func (*FileSystemBase) Unlink(path string) int { 417 return -ENOSYS 418} 419 420// Rmdir removes a directory. 421// The FileSystemBase implementation returns -ENOSYS. 422func (*FileSystemBase) Rmdir(path string) int { 423 return -ENOSYS 424} 425 426// Link creates a hard link to a file. 427// The FileSystemBase implementation returns -ENOSYS. 428func (*FileSystemBase) Link(oldpath string, newpath string) int { 429 return -ENOSYS 430} 431 432// Symlink creates a symbolic link. 433// The FileSystemBase implementation returns -ENOSYS. 434func (*FileSystemBase) Symlink(target string, newpath string) int { 435 return -ENOSYS 436} 437 438// Readlink reads the target of a symbolic link. 439// The FileSystemBase implementation returns -ENOSYS. 440func (*FileSystemBase) Readlink(path string) (int, string) { 441 return -ENOSYS, "" 442} 443 444// Rename renames a file. 445// The FileSystemBase implementation returns -ENOSYS. 446func (*FileSystemBase) Rename(oldpath string, newpath string) int { 447 return -ENOSYS 448} 449 450// Chmod changes the permission bits of a file. 451// The FileSystemBase implementation returns -ENOSYS. 452func (*FileSystemBase) Chmod(path string, mode uint32) int { 453 return -ENOSYS 454} 455 456// Chown changes the owner and group of a file. 457// The FileSystemBase implementation returns -ENOSYS. 458func (*FileSystemBase) Chown(path string, uid uint32, gid uint32) int { 459 return -ENOSYS 460} 461 462// Utimens changes the access and modification times of a file. 463// The FileSystemBase implementation returns -ENOSYS. 464func (*FileSystemBase) Utimens(path string, tmsp []Timespec) int { 465 return -ENOSYS 466} 467 468// Access checks file access permissions. 469// The FileSystemBase implementation returns -ENOSYS. 470func (*FileSystemBase) Access(path string, mask uint32) int { 471 return -ENOSYS 472} 473 474// Create creates and opens a file. 475// The flags are a combination of the fuse.O_* constants. 476// The FileSystemBase implementation returns -ENOSYS. 477func (*FileSystemBase) Create(path string, flags int, mode uint32) (int, uint64) { 478 return -ENOSYS, ^uint64(0) 479} 480 481// Open opens a file. 482// The flags are a combination of the fuse.O_* constants. 483// The FileSystemBase implementation returns -ENOSYS. 484func (*FileSystemBase) Open(path string, flags int) (int, uint64) { 485 return -ENOSYS, ^uint64(0) 486} 487 488// Getattr gets file attributes. 489// The FileSystemBase implementation returns -ENOSYS. 490func (*FileSystemBase) Getattr(path string, stat *Stat_t, fh uint64) int { 491 return -ENOSYS 492} 493 494// Truncate changes the size of a file. 495// The FileSystemBase implementation returns -ENOSYS. 496func (*FileSystemBase) Truncate(path string, size int64, fh uint64) int { 497 return -ENOSYS 498} 499 500// Read reads data from a file. 501// The FileSystemBase implementation returns -ENOSYS. 502func (*FileSystemBase) Read(path string, buff []byte, ofst int64, fh uint64) int { 503 return -ENOSYS 504} 505 506// Write writes data to a file. 507// The FileSystemBase implementation returns -ENOSYS. 508func (*FileSystemBase) Write(path string, buff []byte, ofst int64, fh uint64) int { 509 return -ENOSYS 510} 511 512// Flush flushes cached file data. 513// The FileSystemBase implementation returns -ENOSYS. 514func (*FileSystemBase) Flush(path string, fh uint64) int { 515 return -ENOSYS 516} 517 518// Release closes an open file. 519// The FileSystemBase implementation returns -ENOSYS. 520func (*FileSystemBase) Release(path string, fh uint64) int { 521 return -ENOSYS 522} 523 524// Fsync synchronizes file contents. 525// The FileSystemBase implementation returns -ENOSYS. 526func (*FileSystemBase) Fsync(path string, datasync bool, fh uint64) int { 527 return -ENOSYS 528} 529 530/* 531// Lock performs a file locking operation. 532// The FileSystemBase implementation returns -ENOSYS. 533func (*FileSystemBase) Lock(path string, cmd int, lock *Lock_t, fh uint64) int { 534 return -ENOSYS 535} 536*/ 537 538// Opendir opens a directory. 539// The FileSystemBase implementation returns -ENOSYS. 540func (*FileSystemBase) Opendir(path string) (int, uint64) { 541 return -ENOSYS, ^uint64(0) 542} 543 544// Readdir reads a directory. 545// The FileSystemBase implementation returns -ENOSYS. 546func (*FileSystemBase) Readdir(path string, 547 fill func(name string, stat *Stat_t, ofst int64) bool, 548 ofst int64, 549 fh uint64) int { 550 return -ENOSYS 551} 552 553// Releasedir closes an open directory. 554// The FileSystemBase implementation returns -ENOSYS. 555func (*FileSystemBase) Releasedir(path string, fh uint64) int { 556 return -ENOSYS 557} 558 559// Fsyncdir synchronizes directory contents. 560// The FileSystemBase implementation returns -ENOSYS. 561func (*FileSystemBase) Fsyncdir(path string, datasync bool, fh uint64) int { 562 return -ENOSYS 563} 564 565// Setxattr sets extended attributes. 566// The FileSystemBase implementation returns -ENOSYS. 567func (*FileSystemBase) Setxattr(path string, name string, value []byte, flags int) int { 568 return -ENOSYS 569} 570 571// Getxattr gets extended attributes. 572// The FileSystemBase implementation returns -ENOSYS. 573func (*FileSystemBase) Getxattr(path string, name string) (int, []byte) { 574 return -ENOSYS, nil 575} 576 577// Removexattr removes extended attributes. 578// The FileSystemBase implementation returns -ENOSYS. 579func (*FileSystemBase) Removexattr(path string, name string) int { 580 return -ENOSYS 581} 582 583// Listxattr lists extended attributes. 584// The FileSystemBase implementation returns -ENOSYS. 585func (*FileSystemBase) Listxattr(path string, fill func(name string) bool) int { 586 return -ENOSYS 587} 588 589var _ FileSystemInterface = (*FileSystemBase)(nil) 590