github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/vfs/file.go (about) 1 package vfs 2 3 import ( 4 "context" 5 "os" 6 "path" 7 "sync" 8 "sync/atomic" 9 "time" 10 11 "github.com/pkg/errors" 12 "github.com/rclone/rclone/fs" 13 "github.com/rclone/rclone/fs/log" 14 "github.com/rclone/rclone/fs/operations" 15 "github.com/rclone/rclone/vfs/vfscommon" 16 ) 17 18 // The File object is tightly coupled to the Dir object. Since they 19 // both have locks there is plenty of potential for deadlocks. In 20 // order to mitigate this, we use the following conventions 21 // 22 // File may **only** call these methods from Dir with the File lock 23 // held. 24 // 25 // Dir.Fs 26 // Dir.VFS 27 // 28 // (As these are read only and do not need to take the Dir mutex.) 29 // 30 // File may **not** call any other Dir methods with the File lock 31 // held. This preserves total lock ordering and makes File subordinate 32 // to Dir as far as locking is concerned, preventing deadlocks. 33 // 34 // File may **not** read any members of Dir directly. 35 36 // File represents a file 37 type File struct { 38 inode uint64 // inode number - read only 39 size int64 // size of file - read and written with atomic int64 - must be 64 bit aligned 40 41 mu sync.RWMutex // protects the following 42 d *Dir // parent directory 43 dPath string // path of parent directory. NB dir rename means all Files are flushed 44 o fs.Object // NB o may be nil if file is being written 45 leaf string // leaf name of the object 46 rwOpenCount int // number of open files on this handle 47 writers []Handle // writers for this file 48 nwriters int32 // len(writers) which is read/updated with atomic 49 readWriters int // how many RWFileHandle are open for writing 50 readWriterClosing bool // is an RWFileHandle currently cosing? 51 modified bool // has the cache file be modified by an RWFileHandle? 52 pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written 53 pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close 54 appendMode bool // file was opened with O_APPEND 55 sys interface{} // user defined info to be attached here 56 57 muRW sync.Mutex // synchronize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove 58 } 59 60 // newFile creates a new File 61 // 62 // o may be nil 63 func newFile(d *Dir, dPath string, o fs.Object, leaf string) *File { 64 f := &File{ 65 d: d, 66 dPath: dPath, 67 o: o, 68 leaf: leaf, 69 inode: newInode(), 70 } 71 if o != nil { 72 f.size = o.Size() 73 } 74 return f 75 } 76 77 // String converts it to printable 78 func (f *File) String() string { 79 if f == nil { 80 return "<nil *File>" 81 } 82 return f.Path() 83 } 84 85 // IsFile returns true for File - satisfies Node interface 86 func (f *File) IsFile() bool { 87 return true 88 } 89 90 // IsDir returns false for File - satisfies Node interface 91 func (f *File) IsDir() bool { 92 return false 93 } 94 95 // Mode bits of the file or directory - satisfies Node interface 96 func (f *File) Mode() (mode os.FileMode) { 97 f.mu.RLock() 98 defer f.mu.RUnlock() 99 mode = f.d.vfs.Opt.FilePerms 100 if f.appendMode { 101 mode |= os.ModeAppend 102 } 103 return mode 104 } 105 106 // Name (base) of the directory - satisfies Node interface 107 func (f *File) Name() (name string) { 108 f.mu.RLock() 109 defer f.mu.RUnlock() 110 return f.leaf 111 } 112 113 // _path returns the full path of the file 114 // use when lock is held 115 func (f *File) _path() string { 116 return path.Join(f.dPath, f.leaf) 117 } 118 119 // Path returns the full path of the file 120 func (f *File) Path() string { 121 f.mu.RLock() 122 dPath, leaf := f.dPath, f.leaf 123 f.mu.RUnlock() 124 return path.Join(dPath, leaf) 125 } 126 127 // osPath returns the full path of the file in the cache in OS format 128 func (f *File) osPath() string { 129 return f.d.vfs.cache.ToOSPath(f.Path()) 130 } 131 132 // Sys returns underlying data source (can be nil) - satisfies Node interface 133 func (f *File) Sys() interface{} { 134 f.mu.RLock() 135 defer f.mu.RUnlock() 136 return f.sys 137 } 138 139 // SetSys sets the underlying data source (can be nil) - satisfies Node interface 140 func (f *File) SetSys(x interface{}) { 141 f.mu.Lock() 142 f.sys = x 143 f.mu.Unlock() 144 } 145 146 // Inode returns the inode number - satisfies Node interface 147 func (f *File) Inode() uint64 { 148 return f.inode 149 } 150 151 // Node returns the Node assocuated with this - satisfies Noder interface 152 func (f *File) Node() Node { 153 return f 154 } 155 156 // applyPendingRename runs a previously set rename operation if there are no 157 // more remaining writers. Call without lock held. 158 func (f *File) applyPendingRename() { 159 f.mu.RLock() 160 fun := f.pendingRenameFun 161 writing := f._writingInProgress() 162 f.mu.RUnlock() 163 if fun == nil || writing { 164 return 165 } 166 fs.Debugf(f.Path(), "Running delayed rename now") 167 if err := fun(context.TODO()); err != nil { 168 fs.Errorf(f.Path(), "delayed File.Rename error: %v", err) 169 } 170 } 171 172 // rename attempts to immediately rename a file if there are no open writers. 173 // Otherwise it will queue the rename operation on the remote until no writers 174 // remain. 175 func (f *File) rename(ctx context.Context, destDir *Dir, newName string) error { 176 f.mu.RLock() 177 d := f.d 178 oldPendingRenameFun := f.pendingRenameFun 179 f.mu.RUnlock() 180 181 if features := d.Fs().Features(); features.Move == nil && features.Copy == nil { 182 err := errors.Errorf("Fs %q can't rename files (no server side Move or Copy)", d.Fs()) 183 fs.Errorf(f.Path(), "Dir.Rename error: %v", err) 184 return err 185 } 186 187 // File.mu is unlocked here to call Dir.Path() 188 newPath := path.Join(destDir.Path(), newName) 189 190 renameCall := func(ctx context.Context) error { 191 // chain rename calls if any 192 if oldPendingRenameFun != nil { 193 err := oldPendingRenameFun(ctx) 194 if err != nil { 195 return err 196 } 197 } 198 199 f.mu.RLock() 200 o := f.o 201 f.mu.RUnlock() 202 if o == nil { 203 return errors.New("Cannot rename: file object is not available") 204 } 205 if o.Remote() == newPath { 206 return nil // no need to rename 207 } 208 209 // do the move of the remote object 210 dstOverwritten, _ := d.Fs().NewObject(ctx, newPath) 211 newObject, err := operations.Move(ctx, d.Fs(), dstOverwritten, newPath, o) 212 if err != nil { 213 fs.Errorf(f.Path(), "File.Rename error: %v", err) 214 return err 215 } 216 217 // newObject can be nil here for example if --dry-run 218 if newObject == nil { 219 err = errors.New("rename failed: nil object returned") 220 fs.Errorf(f.Path(), "File.Rename %v", err) 221 return err 222 } 223 // Update the node with the new details 224 fs.Debugf(f.Path(), "Updating file with %v %p", newObject, f) 225 // f.rename(destDir, newObject) 226 f.mu.Lock() 227 f.o = newObject 228 f.pendingRenameFun = nil 229 f.mu.Unlock() 230 return nil 231 } 232 233 // Rename in the cache if it exists 234 if f.d.vfs.cache != nil && f.d.vfs.cache.Exists(f.Path()) { 235 if err := f.d.vfs.cache.Rename(f.Path(), newPath); err != nil { 236 fs.Infof(f.Path(), "File.Rename failed in Cache: %v", err) 237 } 238 } 239 240 // rename the file object 241 dPath := destDir.Path() 242 f.mu.Lock() 243 f.d = destDir 244 f.dPath = dPath 245 f.leaf = newName 246 writing := f._writingInProgress() 247 f.mu.Unlock() 248 249 if writing { 250 fs.Debugf(f.Path(), "File is currently open, delaying rename %p", f) 251 f.mu.Lock() 252 f.pendingRenameFun = renameCall 253 f.mu.Unlock() 254 return nil 255 } 256 257 return renameCall(ctx) 258 } 259 260 // addWriter adds a write handle to the file 261 func (f *File) addWriter(h Handle) { 262 f.mu.Lock() 263 f.writers = append(f.writers, h) 264 atomic.AddInt32(&f.nwriters, 1) 265 if _, ok := h.(*RWFileHandle); ok { 266 f.readWriters++ 267 } 268 f.mu.Unlock() 269 } 270 271 // delWriter removes a write handle from the file 272 func (f *File) delWriter(h Handle, modifiedCacheFile bool) (lastWriterAndModified bool) { 273 f.mu.Lock() 274 defer f.applyPendingRename() 275 defer f.mu.Unlock() 276 var found = -1 277 for i := range f.writers { 278 if f.writers[i] == h { 279 found = i 280 break 281 } 282 } 283 if found >= 0 { 284 f.writers = append(f.writers[:found], f.writers[found+1:]...) 285 atomic.AddInt32(&f.nwriters, -1) 286 } else { 287 fs.Debugf(f._path(), "File.delWriter couldn't find handle") 288 } 289 if _, ok := h.(*RWFileHandle); ok { 290 f.readWriters-- 291 } 292 f.readWriterClosing = true 293 if modifiedCacheFile { 294 f.modified = true 295 } 296 lastWriterAndModified = len(f.writers) == 0 && f.modified 297 if lastWriterAndModified { 298 f.modified = false 299 } 300 return 301 } 302 303 // addRWOpen should be called by ReadWriteHandle when they have 304 // actually opened the file for read or write. 305 func (f *File) addRWOpen() { 306 f.mu.Lock() 307 f.rwOpenCount++ 308 f.mu.Unlock() 309 } 310 311 // delRWOpen should be called by ReadWriteHandle when they have closed 312 // an actually opene file for read or write. 313 func (f *File) delRWOpen() { 314 f.mu.Lock() 315 f.rwOpenCount-- 316 f.mu.Unlock() 317 } 318 319 // rwOpens returns how many active open ReadWriteHandles there are. 320 // Note that file handles which are in pending open state aren't 321 // counted. 322 func (f *File) rwOpens() int { 323 f.mu.RLock() 324 defer f.mu.RUnlock() 325 return f.rwOpenCount 326 } 327 328 // finishWriterClose resets the readWriterClosing flag 329 func (f *File) finishWriterClose() { 330 f.mu.Lock() 331 f.readWriterClosing = false 332 f.mu.Unlock() 333 f.applyPendingRename() 334 } 335 336 // activeWriters returns the number of writers on the file 337 // 338 // Note that we don't take the mutex here. If we do then we can get a 339 // deadlock. 340 func (f *File) activeWriters() int { 341 return int(atomic.LoadInt32(&f.nwriters)) 342 } 343 344 // ModTime returns the modified time of the file 345 // 346 // if NoModTime is set then it returns the mod time of the directory 347 func (f *File) ModTime() (modTime time.Time) { 348 f.mu.RLock() 349 d, o, pendingModTime := f.d, f.o, f.pendingModTime 350 f.mu.RUnlock() 351 352 if d.vfs.Opt.NoModTime { 353 return d.ModTime() 354 } 355 if !pendingModTime.IsZero() { 356 return pendingModTime 357 } 358 if o == nil { 359 return d.ModTime() 360 } 361 return o.ModTime(context.TODO()) 362 } 363 364 // nonNegative returns 0 if i is -ve, i otherwise 365 func nonNegative(i int64) int64 { 366 if i >= 0 { 367 return i 368 } 369 return 0 370 } 371 372 // Size of the file 373 func (f *File) Size() int64 { 374 f.mu.RLock() 375 defer f.mu.RUnlock() 376 377 // if o is nil it isn't valid yet or there are writers, so return the size so far 378 if f._writingInProgress() { 379 return atomic.LoadInt64(&f.size) 380 } 381 return nonNegative(f.o.Size()) 382 } 383 384 // SetModTime sets the modtime for the file 385 func (f *File) SetModTime(modTime time.Time) error { 386 if f.d.vfs.Opt.ReadOnly { 387 return EROFS 388 } 389 f.mu.Lock() 390 defer f.mu.Unlock() 391 392 f.pendingModTime = modTime 393 394 // Only update the ModTime when there are no writers, setObject will do it 395 if !f._writingInProgress() { 396 return f._applyPendingModTime() 397 } 398 399 // queue up for later, hoping f.o becomes available 400 return nil 401 } 402 403 // Apply a pending mod time 404 // Call with the mutex held 405 func (f *File) _applyPendingModTime() error { 406 if f.pendingModTime.IsZero() { 407 return nil 408 } 409 410 defer func() { f.pendingModTime = time.Time{} }() 411 412 if f.o == nil { 413 return errors.New("Cannot apply ModTime, file object is not available") 414 } 415 416 // set the time of the file in the cache 417 if f.d.vfs.cache != nil { 418 f.d.vfs.cache.SetModTime(f._path(), f.pendingModTime) 419 } 420 421 // set the time of the object 422 err := f.o.SetModTime(context.TODO(), f.pendingModTime) 423 switch err { 424 case nil: 425 fs.Debugf(f._path(), "File._applyPendingModTime OK") 426 case fs.ErrorCantSetModTime, fs.ErrorCantSetModTimeWithoutDelete: 427 // do nothing, in order to not break "touch somefile" if it exists already 428 default: 429 fs.Debugf(f._path(), "File._applyPendingModTime error: %v", err) 430 return err 431 } 432 433 return nil 434 } 435 436 // _writingInProgress returns true of there are any open writers 437 // Call with read lock held 438 func (f *File) _writingInProgress() bool { 439 return f.o == nil || len(f.writers) != 0 || f.readWriterClosing 440 } 441 442 // Update the size while writing 443 func (f *File) setSize(n int64) { 444 atomic.StoreInt64(&f.size, n) 445 } 446 447 // Update the object when written and add it to the directory 448 func (f *File) setObject(o fs.Object) { 449 f.mu.Lock() 450 f.o = o 451 _ = f._applyPendingModTime() 452 f.mu.Unlock() 453 454 // Release File.mu before calling Dir method 455 f.d.addObject(f) 456 } 457 458 // Update the object but don't update the directory cache - for use by 459 // the directory cache 460 func (f *File) setObjectNoUpdate(o fs.Object) { 461 f.mu.Lock() 462 f.o = o 463 f.mu.Unlock() 464 } 465 466 // Get the current fs.Object - may be nil 467 func (f *File) getObject() fs.Object { 468 f.mu.RLock() 469 defer f.mu.RUnlock() 470 return f.o 471 } 472 473 // exists returns whether the file exists already 474 func (f *File) exists() bool { 475 f.mu.RLock() 476 defer f.mu.RUnlock() 477 return f.o != nil 478 } 479 480 // Wait for f.o to become non nil for a short time returning it or an 481 // error. Use when opening a read handle. 482 // 483 // Call without the mutex held 484 func (f *File) waitForValidObject() (o fs.Object, err error) { 485 for i := 0; i < 50; i++ { 486 f.mu.RLock() 487 o = f.o 488 nwriters := len(f.writers) 489 wclosing := f.readWriterClosing 490 f.mu.RUnlock() 491 if o != nil { 492 return o, nil 493 } 494 if nwriters == 0 && !wclosing { 495 return nil, errors.New("can't open file - writer failed") 496 } 497 time.Sleep(100 * time.Millisecond) 498 } 499 return nil, ENOENT 500 } 501 502 // openRead open the file for read 503 func (f *File) openRead() (fh *ReadFileHandle, err error) { 504 // if o is nil it isn't valid yet 505 _, err = f.waitForValidObject() 506 if err != nil { 507 return nil, err 508 } 509 // fs.Debugf(f.Path(), "File.openRead") 510 511 fh, err = newReadFileHandle(f) 512 if err != nil { 513 fs.Debugf(f.Path(), "File.openRead failed: %v", err) 514 return nil, err 515 } 516 return fh, nil 517 } 518 519 // openWrite open the file for write 520 func (f *File) openWrite(flags int) (fh *WriteFileHandle, err error) { 521 f.mu.RLock() 522 d := f.d 523 f.mu.RUnlock() 524 525 if d.vfs.Opt.ReadOnly { 526 return nil, EROFS 527 } 528 // fs.Debugf(f.Path(), "File.openWrite") 529 530 fh, err = newWriteFileHandle(d, f, f.Path(), flags) 531 if err != nil { 532 fs.Debugf(f.Path(), "File.openWrite failed: %v", err) 533 return nil, err 534 } 535 return fh, nil 536 } 537 538 // openRW open the file for read and write using a temporay file 539 // 540 // It uses the open flags passed in. 541 func (f *File) openRW(flags int) (fh *RWFileHandle, err error) { 542 f.mu.RLock() 543 d := f.d 544 f.mu.RUnlock() 545 546 // FIXME chunked 547 if flags&accessModeMask != os.O_RDONLY && d.vfs.Opt.ReadOnly { 548 return nil, EROFS 549 } 550 // fs.Debugf(f.Path(), "File.openRW") 551 552 fh, err = newRWFileHandle(d, f, flags) 553 if err != nil { 554 fs.Debugf(f.Path(), "File.openRW failed: %v", err) 555 return nil, err 556 } 557 return fh, nil 558 } 559 560 // Sync the file 561 // 562 // Note that we don't do anything except return OK 563 func (f *File) Sync() error { 564 return nil 565 } 566 567 // Remove the file 568 func (f *File) Remove() error { 569 f.mu.RLock() 570 d := f.d 571 f.mu.RUnlock() 572 573 if d.vfs.Opt.ReadOnly { 574 return EROFS 575 } 576 f.muRW.Lock() // muRW must be locked before mu to avoid 577 f.mu.Lock() // deadlock in RWFileHandle.openPending and .close 578 if f.o != nil { 579 err := f.o.Remove(context.TODO()) 580 if err != nil { 581 fs.Debugf(f._path(), "File.Remove file error: %v", err) 582 f.mu.Unlock() 583 f.muRW.Unlock() 584 return err 585 } 586 } 587 f.mu.Unlock() 588 f.muRW.Unlock() 589 590 // Remove the item from the directory listing 591 // called with File.mu released 592 d.delObject(f.Name()) 593 // Remove the object from the cache 594 if d.vfs.cache != nil { 595 d.vfs.cache.Remove(f.Path()) 596 } 597 return nil 598 } 599 600 // RemoveAll the file - same as remove for files 601 func (f *File) RemoveAll() error { 602 return f.Remove() 603 } 604 605 // DirEntry returns the underlying fs.DirEntry - may be nil 606 func (f *File) DirEntry() (entry fs.DirEntry) { 607 f.mu.RLock() 608 defer f.mu.RUnlock() 609 return f.o 610 } 611 612 // Dir returns the directory this file is in 613 func (f *File) Dir() *Dir { 614 f.mu.RLock() 615 defer f.mu.RUnlock() 616 return f.d 617 } 618 619 // VFS returns the instance of the VFS 620 func (f *File) VFS() *VFS { 621 f.mu.RLock() 622 defer f.mu.RUnlock() 623 return f.d.vfs 624 } 625 626 // Fs returns the underlying Fs for the file 627 func (f *File) Fs() fs.Fs { 628 f.mu.RLock() 629 defer f.mu.RUnlock() 630 return f.d.Fs() 631 } 632 633 // Open a file according to the flags provided 634 // 635 // O_RDONLY open the file read-only. 636 // O_WRONLY open the file write-only. 637 // O_RDWR open the file read-write. 638 // 639 // O_APPEND append data to the file when writing. 640 // O_CREATE create a new file if none exists. 641 // O_EXCL used with O_CREATE, file must not exist 642 // O_SYNC open for synchronous I/O. 643 // O_TRUNC if possible, truncate file when opene 644 // 645 // We ignore O_SYNC and O_EXCL 646 func (f *File) Open(flags int) (fd Handle, err error) { 647 defer log.Trace(f.Path(), "flags=%s", decodeOpenFlags(flags))("fd=%v, err=%v", &fd, &err) 648 var ( 649 write bool // if set need write support 650 read bool // if set need read support 651 rdwrMode = flags & accessModeMask 652 ) 653 654 // http://pubs.opengroup.org/onlinepubs/7908799/xsh/open.html 655 // The result of using O_TRUNC with O_RDONLY is undefined. 656 // Linux seems to truncate the file, but we prefer to return EINVAL 657 if rdwrMode == os.O_RDONLY && flags&os.O_TRUNC != 0 { 658 return nil, EINVAL 659 } 660 661 // Figure out the read/write intents 662 switch { 663 case rdwrMode == os.O_RDONLY: 664 read = true 665 case rdwrMode == os.O_WRONLY: 666 write = true 667 case rdwrMode == os.O_RDWR: 668 read = true 669 write = true 670 default: 671 fs.Debugf(f.Path(), "Can't figure out how to open with flags: 0x%X", flags) 672 return nil, EPERM 673 } 674 675 // If append is set then set read to force openRW 676 if flags&os.O_APPEND != 0 { 677 read = true 678 f.mu.Lock() 679 f.appendMode = true 680 f.mu.Unlock() 681 } 682 683 // If truncate is set then set write to force openRW 684 if flags&os.O_TRUNC != 0 { 685 write = true 686 } 687 688 // Open the correct sort of handle 689 f.mu.RLock() 690 d := f.d 691 f.mu.RUnlock() 692 CacheMode := d.vfs.Opt.CacheMode 693 if CacheMode >= vfscommon.CacheModeMinimal && (d.vfs.cache.Opens(f.Path()) > 0 || d.vfs.cache.Exists(f.Path())) { 694 fd, err = f.openRW(flags) 695 } else if read && write { 696 if CacheMode >= vfscommon.CacheModeMinimal { 697 fd, err = f.openRW(flags) 698 } else { 699 // Open write only and hope the user doesn't 700 // want to read. If they do they will get an 701 // EPERM plus an Error log. 702 fd, err = f.openWrite(flags) 703 } 704 } else if write { 705 if CacheMode >= vfscommon.CacheModeWrites { 706 fd, err = f.openRW(flags) 707 } else { 708 fd, err = f.openWrite(flags) 709 } 710 } else if read { 711 if CacheMode >= vfscommon.CacheModeFull { 712 fd, err = f.openRW(flags) 713 } else { 714 fd, err = f.openRead() 715 } 716 } else { 717 fs.Debugf(f.Path(), "Can't figure out how to open with flags: 0x%X", flags) 718 return nil, EPERM 719 } 720 // if creating a file, add the file to the directory 721 if err == nil && flags&os.O_CREATE != 0 { 722 // called without File.mu held 723 d.addObject(f) 724 } 725 return fd, err 726 } 727 728 // Truncate changes the size of the named file. 729 func (f *File) Truncate(size int64) (err error) { 730 // make a copy of fh.writers with the lock held then unlock so 731 // we can call other file methods. 732 f.mu.Lock() 733 writers := make([]Handle, len(f.writers)) 734 copy(writers, f.writers) 735 o := f.o 736 f.mu.Unlock() 737 738 // FIXME: handle closing writer 739 740 // If have writers then call truncate for each writer 741 if len(writers) != 0 { 742 fs.Debugf(f.Path(), "Truncating %d file handles", len(writers)) 743 for _, h := range writers { 744 truncateErr := h.Truncate(size) 745 if truncateErr != nil { 746 err = truncateErr 747 } 748 } 749 return err 750 } 751 752 // If no writers, and size is already correct then all done 753 if o.Size() == size { 754 return nil 755 } 756 757 fs.Debugf(f.Path(), "Truncating file") 758 759 // Otherwise if no writers then truncate the file by opening 760 // the file and truncating it. 761 flags := os.O_WRONLY 762 if size == 0 { 763 flags |= os.O_TRUNC 764 } 765 fh, err := f.Open(flags) 766 if err != nil { 767 return err 768 } 769 defer fs.CheckClose(fh, &err) 770 if size != 0 { 771 return fh.Truncate(size) 772 } 773 return nil 774 }