Source file src/os/file.go
1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package os provides a platform-independent interface to operating system 6 // functionality. The design is Unix-like, although the error handling is 7 // Go-like; failing calls return values of type error rather than error numbers. 8 // Often, more information is available within the error. For example, 9 // if a call that takes a file name fails, such as [Open] or [Stat], the error 10 // will include the failing file name when printed and will be of type 11 // [*PathError], which may be unpacked for more information. 12 // 13 // The os interface is intended to be uniform across all operating systems. 14 // Features not generally available appear in the system-specific package syscall. 15 // 16 // Here is a simple example, opening a file and reading some of it. 17 // 18 // file, err := os.Open("file.go") // For read access. 19 // if err != nil { 20 // log.Fatal(err) 21 // } 22 // 23 // If the open fails, the error string will be self-explanatory, like 24 // 25 // open file.go: no such file or directory 26 // 27 // The file's data can then be read into a slice of bytes. Read and 28 // Write take their byte counts from the length of the argument slice. 29 // 30 // data := make([]byte, 100) 31 // count, err := file.Read(data) 32 // if err != nil { 33 // log.Fatal(err) 34 // } 35 // fmt.Printf("read %d bytes: %q\n", count, data[:count]) 36 // 37 // # Concurrency 38 // 39 // The methods of [File] correspond to file system operations. All are 40 // safe for concurrent use. The maximum number of concurrent 41 // operations on a File may be limited by the OS or the system. The 42 // number should be high, but exceeding it may degrade performance or 43 // cause other issues. 44 package os 45 46 import ( 47 "errors" 48 "internal/filepathlite" 49 "internal/poll" 50 "internal/testlog" 51 "io" 52 "io/fs" 53 "runtime" 54 "slices" 55 "syscall" 56 "time" 57 "unsafe" 58 ) 59 60 // Name returns the name of the file as presented to Open. 61 // 62 // It is safe to call Name after [Close]. 63 func (f *File) Name() string { return f.name } 64 65 // Stdin, Stdout, and Stderr are open Files pointing to the standard input, 66 // standard output, and standard error file descriptors. 67 // 68 // Note that the Go runtime writes to standard error for panics and crashes; 69 // closing Stderr may cause those messages to go elsewhere, perhaps 70 // to a file opened later. 71 var ( 72 Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin") 73 Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout") 74 Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr") 75 ) 76 77 // Flags to OpenFile wrapping those of the underlying system. Not all 78 // flags may be implemented on a given system. 79 const ( 80 // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. 81 O_RDONLY int = syscall.O_RDONLY // open the file read-only. 82 O_WRONLY int = syscall.O_WRONLY // open the file write-only. 83 O_RDWR int = syscall.O_RDWR // open the file read-write. 84 // The remaining values may be or'ed in to control behavior. 85 O_APPEND int = syscall.O_APPEND // append data to the file when writing. 86 O_CREATE int = syscall.O_CREAT // create a new file if none exists. 87 O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist. 88 O_SYNC int = syscall.O_SYNC // open for synchronous I/O. 89 O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened. 90 ) 91 92 // Seek whence values. 93 // 94 // Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd. 95 const ( 96 SEEK_SET int = 0 // seek relative to the origin of the file 97 SEEK_CUR int = 1 // seek relative to the current offset 98 SEEK_END int = 2 // seek relative to the end 99 ) 100 101 // LinkError records an error during a link or symlink or rename 102 // system call and the paths that caused it. 103 type LinkError struct { 104 Op string 105 Old string 106 New string 107 Err error 108 } 109 110 func (e *LinkError) Error() string { 111 return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error() 112 } 113 114 func (e *LinkError) Unwrap() error { 115 return e.Err 116 } 117 118 // NewFile returns a new [File] with the given file descriptor and name. 119 // The returned value will be nil if fd is not a valid file descriptor. 120 // 121 // NewFile's behavior differs on some platforms: 122 // 123 // - On Unix, if fd is in non-blocking mode, NewFile will attempt to return a pollable file. 124 // - On Windows, if fd is opened for asynchronous I/O (that is, [syscall.FILE_FLAG_OVERLAPPED] 125 // has been specified in the [syscall.CreateFile] call), NewFile will attempt to return a pollable 126 // file by associating fd with the Go runtime I/O completion port. 127 // The I/O operations will be performed synchronously if the association fails. 128 // 129 // Only pollable files support [File.SetDeadline], [File.SetReadDeadline], and [File.SetWriteDeadline]. 130 // 131 // After passing it to NewFile, fd may become invalid under the same conditions described 132 // in the comments of [File.Fd], and the same constraints apply. 133 func NewFile(fd uintptr, name string) *File { 134 return newFileFromNewFile(fd, name) 135 } 136 137 // Read reads up to len(b) bytes from the File and stores them in b. 138 // It returns the number of bytes read and any error encountered. 139 // At end of file, Read returns 0, io.EOF. 140 func (f *File) Read(b []byte) (n int, err error) { 141 if err := f.checkValid("read"); err != nil { 142 return 0, err 143 } 144 n, e := f.read(b) 145 return n, f.wrapErr("read", e) 146 } 147 148 // ReadAt reads len(b) bytes from the File starting at byte offset off. 149 // It returns the number of bytes read and the error, if any. 150 // ReadAt always returns a non-nil error when n < len(b). 151 // At end of file, that error is io.EOF. 152 func (f *File) ReadAt(b []byte, off int64) (n int, err error) { 153 if err := f.checkValid("read"); err != nil { 154 return 0, err 155 } 156 157 if off < 0 { 158 return 0, &PathError{Op: "readat", Path: f.name, Err: errors.New("negative offset")} 159 } 160 161 for len(b) > 0 { 162 m, e := f.pread(b, off) 163 if e != nil { 164 err = f.wrapErr("read", e) 165 break 166 } 167 n += m 168 b = b[m:] 169 off += int64(m) 170 } 171 return 172 } 173 174 // ReadFrom implements io.ReaderFrom. 175 func (f *File) ReadFrom(r io.Reader) (n int64, err error) { 176 if err := f.checkValid("write"); err != nil { 177 return 0, err 178 } 179 n, handled, e := f.readFrom(r) 180 if !handled { 181 return genericReadFrom(f, r) // without wrapping 182 } 183 return n, f.wrapErr("write", e) 184 } 185 186 // noReadFrom can be embedded alongside another type to 187 // hide the ReadFrom method of that other type. 188 type noReadFrom struct{} 189 190 // ReadFrom hides another ReadFrom method. 191 // It should never be called. 192 func (noReadFrom) ReadFrom(io.Reader) (int64, error) { 193 panic("can't happen") 194 } 195 196 // fileWithoutReadFrom implements all the methods of *File other 197 // than ReadFrom. This is used to permit ReadFrom to call io.Copy 198 // without leading to a recursive call to ReadFrom. 199 type fileWithoutReadFrom struct { 200 noReadFrom 201 *File 202 } 203 204 func genericReadFrom(f *File, r io.Reader) (int64, error) { 205 return io.Copy(fileWithoutReadFrom{File: f}, r) 206 } 207 208 // Write writes len(b) bytes from b to the File. 209 // It returns the number of bytes written and an error, if any. 210 // Write returns a non-nil error when n != len(b). 211 func (f *File) Write(b []byte) (n int, err error) { 212 if err := f.checkValid("write"); err != nil { 213 return 0, err 214 } 215 n, e := f.write(b) 216 if n < 0 { 217 n = 0 218 } 219 if n != len(b) { 220 err = io.ErrShortWrite 221 } 222 223 epipecheck(f, e) 224 225 if e != nil { 226 err = f.wrapErr("write", e) 227 } 228 229 return n, err 230 } 231 232 var errWriteAtInAppendMode = errors.New("os: invalid use of WriteAt on file opened with O_APPEND") 233 234 // WriteAt writes len(b) bytes to the File starting at byte offset off. 235 // It returns the number of bytes written and an error, if any. 236 // WriteAt returns a non-nil error when n != len(b). 237 // 238 // If file was opened with the [O_APPEND] flag, WriteAt returns an error. 239 func (f *File) WriteAt(b []byte, off int64) (n int, err error) { 240 if err := f.checkValid("write"); err != nil { 241 return 0, err 242 } 243 if f.appendMode { 244 return 0, errWriteAtInAppendMode 245 } 246 247 if off < 0 { 248 return 0, &PathError{Op: "writeat", Path: f.name, Err: errors.New("negative offset")} 249 } 250 251 for len(b) > 0 { 252 m, e := f.pwrite(b, off) 253 if e != nil { 254 err = f.wrapErr("write", e) 255 break 256 } 257 n += m 258 b = b[m:] 259 off += int64(m) 260 } 261 return 262 } 263 264 // WriteTo implements io.WriterTo. 265 func (f *File) WriteTo(w io.Writer) (n int64, err error) { 266 if err := f.checkValid("read"); err != nil { 267 return 0, err 268 } 269 n, handled, e := f.writeTo(w) 270 if handled { 271 return n, f.wrapErr("read", e) 272 } 273 return genericWriteTo(f, w) // without wrapping 274 } 275 276 // noWriteTo can be embedded alongside another type to 277 // hide the WriteTo method of that other type. 278 type noWriteTo struct{} 279 280 // WriteTo hides another WriteTo method. 281 // It should never be called. 282 func (noWriteTo) WriteTo(io.Writer) (int64, error) { 283 panic("can't happen") 284 } 285 286 // fileWithoutWriteTo implements all the methods of *File other 287 // than WriteTo. This is used to permit WriteTo to call io.Copy 288 // without leading to a recursive call to WriteTo. 289 type fileWithoutWriteTo struct { 290 noWriteTo 291 *File 292 } 293 294 func genericWriteTo(f *File, w io.Writer) (int64, error) { 295 return io.Copy(w, fileWithoutWriteTo{File: f}) 296 } 297 298 // Seek sets the offset for the next Read or Write on file to offset, interpreted 299 // according to whence: 0 means relative to the origin of the file, 1 means 300 // relative to the current offset, and 2 means relative to the end. 301 // It returns the new offset and an error, if any. 302 // The behavior of Seek on a file opened with [O_APPEND] is not specified. 303 func (f *File) Seek(offset int64, whence int) (ret int64, err error) { 304 if err := f.checkValid("seek"); err != nil { 305 return 0, err 306 } 307 r, e := f.seek(offset, whence) 308 if e == nil && f.dirinfo.Load() != nil && r != 0 { 309 e = syscall.EISDIR 310 } 311 if e != nil { 312 return 0, f.wrapErr("seek", e) 313 } 314 return r, nil 315 } 316 317 // WriteString is like Write, but writes the contents of string s rather than 318 // a slice of bytes. 319 func (f *File) WriteString(s string) (n int, err error) { 320 b := unsafe.Slice(unsafe.StringData(s), len(s)) 321 return f.Write(b) 322 } 323 324 // Mkdir creates a new directory with the specified name and permission 325 // bits (before umask). 326 // If there is an error, it will be of type [*PathError]. 327 func Mkdir(name string, perm FileMode) error { 328 longName := fixLongPath(name) 329 e := ignoringEINTR(func() error { 330 return syscall.Mkdir(longName, syscallMode(perm)) 331 }) 332 333 if e != nil { 334 return &PathError{Op: "mkdir", Path: name, Err: e} 335 } 336 337 // mkdir(2) itself won't handle the sticky bit on *BSD and Solaris 338 if !supportsCreateWithStickyBit && perm&ModeSticky != 0 { 339 e = setStickyBit(name) 340 341 if e != nil { 342 Remove(name) 343 return e 344 } 345 } 346 347 return nil 348 } 349 350 // setStickyBit adds ModeSticky to the permission bits of path, non atomic. 351 func setStickyBit(name string) error { 352 fi, err := Stat(name) 353 if err != nil { 354 return err 355 } 356 return Chmod(name, fi.Mode()|ModeSticky) 357 } 358 359 // Chdir changes the current working directory to the named directory. 360 // If there is an error, it will be of type [*PathError]. 361 func Chdir(dir string) error { 362 if e := syscall.Chdir(dir); e != nil { 363 testlog.Open(dir) // observe likely non-existent directory 364 return &PathError{Op: "chdir", Path: dir, Err: e} 365 } 366 if runtime.GOOS == "windows" { 367 abs := filepathlite.IsAbs(dir) 368 getwdCache.Lock() 369 if abs { 370 getwdCache.dir = dir 371 } else { 372 getwdCache.dir = "" 373 } 374 getwdCache.Unlock() 375 } 376 if log := testlog.Logger(); log != nil { 377 wd, err := Getwd() 378 if err == nil { 379 log.Chdir(wd) 380 } 381 } 382 return nil 383 } 384 385 // Open opens the named file for reading. If successful, methods on 386 // the returned file can be used for reading; the associated file 387 // descriptor has mode [O_RDONLY]. 388 // If there is an error, it will be of type [*PathError]. 389 func Open(name string) (*File, error) { 390 return OpenFile(name, O_RDONLY, 0) 391 } 392 393 // Create creates or truncates the named file. If the file already exists, 394 // it is truncated. If the file does not exist, it is created with mode 0o666 395 // (before umask). If successful, methods on the returned File can 396 // be used for I/O; the associated file descriptor has mode [O_RDWR]. 397 // The directory containing the file must already exist. 398 // If there is an error, it will be of type [*PathError]. 399 func Create(name string) (*File, error) { 400 return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666) 401 } 402 403 // OpenFile is the generalized open call; most users will use Open 404 // or Create instead. It opens the named file with specified flag 405 // ([O_RDONLY] etc.). If the file does not exist, and the [O_CREATE] flag 406 // is passed, it is created with mode perm (before umask); 407 // the containing directory must exist. If successful, 408 // methods on the returned File can be used for I/O. 409 // If there is an error, it will be of type [*PathError]. 410 func OpenFile(name string, flag int, perm FileMode) (*File, error) { 411 testlog.Open(name) 412 f, err := openFileNolog(name, flag, perm) 413 if err != nil { 414 return nil, err 415 } 416 f.appendMode = flag&O_APPEND != 0 417 418 return f, nil 419 } 420 421 var errPathEscapes = errors.New("path escapes from parent") 422 423 // openDir opens a file which is assumed to be a directory. As such, it skips 424 // the syscalls that make the file descriptor non-blocking as these take time 425 // and will fail on file descriptors for directories. 426 func openDir(name string) (*File, error) { 427 testlog.Open(name) 428 return openDirNolog(name) 429 } 430 431 // Rename renames (moves) oldpath to newpath. 432 // If newpath already exists and is not a directory, Rename replaces it. 433 // If newpath already exists and is a directory, Rename returns an error. 434 // OS-specific restrictions may apply when oldpath and newpath are in different directories. 435 // Even within the same directory, on non-Unix platforms Rename is not an atomic operation. 436 // If there is an error, it will be of type *LinkError. 437 func Rename(oldpath, newpath string) error { 438 return rename(oldpath, newpath) 439 } 440 441 // Readlink returns the destination of the named symbolic link. 442 // If there is an error, it will be of type [*PathError]. 443 // 444 // If the link destination is relative, Readlink returns the relative path 445 // without resolving it to an absolute one. 446 func Readlink(name string) (string, error) { 447 return readlink(name) 448 } 449 450 // Many functions in package syscall return a count of -1 instead of 0. 451 // Using fixCount(call()) instead of call() corrects the count. 452 func fixCount(n int, err error) (int, error) { 453 if n < 0 { 454 n = 0 455 } 456 return n, err 457 } 458 459 // checkWrapErr is the test hook to enable checking unexpected wrapped errors of poll.ErrFileClosing. 460 // It is set to true in the export_test.go for tests (including fuzz tests). 461 var checkWrapErr = false 462 463 // wrapErr wraps an error that occurred during an operation on an open file. 464 // It passes io.EOF through unchanged, otherwise converts 465 // poll.ErrFileClosing to ErrClosed and wraps the error in a PathError. 466 func (f *File) wrapErr(op string, err error) error { 467 if err == nil || err == io.EOF { 468 return err 469 } 470 if err == poll.ErrFileClosing { 471 err = ErrClosed 472 } else if checkWrapErr && errors.Is(err, poll.ErrFileClosing) { 473 panic("unexpected error wrapping poll.ErrFileClosing: " + err.Error()) 474 } 475 return &PathError{Op: op, Path: f.name, Err: err} 476 } 477 478 // TempDir returns the default directory to use for temporary files. 479 // 480 // On Unix systems, it returns $TMPDIR if non-empty, else /tmp. 481 // On Windows, it uses GetTempPath, returning the first non-empty 482 // value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory. 483 // On Plan 9, it returns /tmp. 484 // 485 // The directory is neither guaranteed to exist nor have accessible 486 // permissions. 487 func TempDir() string { 488 return tempDir() 489 } 490 491 // UserCacheDir returns the default root directory to use for user-specific 492 // cached data. Users should create their own application-specific subdirectory 493 // within this one and use that. 494 // 495 // On Unix systems, it returns $XDG_CACHE_HOME as specified by 496 // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if 497 // non-empty, else $HOME/.cache. 498 // On Darwin, it returns $HOME/Library/Caches. 499 // On Windows, it returns %LocalAppData%. 500 // On Plan 9, it returns $home/lib/cache. 501 // 502 // If the location cannot be determined (for example, $HOME is not defined) or 503 // the path in $XDG_CACHE_HOME is relative, then it will return an error. 504 func UserCacheDir() (string, error) { 505 var dir string 506 507 switch runtime.GOOS { 508 case "windows": 509 dir = Getenv("LocalAppData") 510 if dir == "" { 511 return "", errors.New("%LocalAppData% is not defined") 512 } 513 514 case "darwin", "ios": 515 dir = Getenv("HOME") 516 if dir == "" { 517 return "", errors.New("$HOME is not defined") 518 } 519 dir += "/Library/Caches" 520 521 case "plan9": 522 dir = Getenv("home") 523 if dir == "" { 524 return "", errors.New("$home is not defined") 525 } 526 dir += "/lib/cache" 527 528 default: // Unix 529 dir = Getenv("XDG_CACHE_HOME") 530 if dir == "" { 531 dir = Getenv("HOME") 532 if dir == "" { 533 return "", errors.New("neither $XDG_CACHE_HOME nor $HOME are defined") 534 } 535 dir += "/.cache" 536 } else if !filepathlite.IsAbs(dir) { 537 return "", errors.New("path in $XDG_CACHE_HOME is relative") 538 } 539 } 540 541 return dir, nil 542 } 543 544 // UserConfigDir returns the default root directory to use for user-specific 545 // configuration data. Users should create their own application-specific 546 // subdirectory within this one and use that. 547 // 548 // On Unix systems, it returns $XDG_CONFIG_HOME as specified by 549 // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if 550 // non-empty, else $HOME/.config. 551 // On Darwin, it returns $HOME/Library/Application Support. 552 // On Windows, it returns %AppData%. 553 // On Plan 9, it returns $home/lib. 554 // 555 // If the location cannot be determined (for example, $HOME is not defined) or 556 // the path in $XDG_CONFIG_HOME is relative, then it will return an error. 557 func UserConfigDir() (string, error) { 558 var dir string 559 560 switch runtime.GOOS { 561 case "windows": 562 dir = Getenv("AppData") 563 if dir == "" { 564 return "", errors.New("%AppData% is not defined") 565 } 566 567 case "darwin", "ios": 568 dir = Getenv("HOME") 569 if dir == "" { 570 return "", errors.New("$HOME is not defined") 571 } 572 dir += "/Library/Application Support" 573 574 case "plan9": 575 dir = Getenv("home") 576 if dir == "" { 577 return "", errors.New("$home is not defined") 578 } 579 dir += "/lib" 580 581 default: // Unix 582 dir = Getenv("XDG_CONFIG_HOME") 583 if dir == "" { 584 dir = Getenv("HOME") 585 if dir == "" { 586 return "", errors.New("neither $XDG_CONFIG_HOME nor $HOME are defined") 587 } 588 dir += "/.config" 589 } else if !filepathlite.IsAbs(dir) { 590 return "", errors.New("path in $XDG_CONFIG_HOME is relative") 591 } 592 } 593 594 return dir, nil 595 } 596 597 // UserHomeDir returns the current user's home directory. 598 // 599 // On Unix, including macOS, it returns the $HOME environment variable. 600 // On Windows, it returns %USERPROFILE%. 601 // On Plan 9, it returns the $home environment variable. 602 // 603 // If the expected variable is not set in the environment, UserHomeDir 604 // returns either a platform-specific default value or a non-nil error. 605 func UserHomeDir() (string, error) { 606 env, enverr := "HOME", "$HOME" 607 switch runtime.GOOS { 608 case "windows": 609 env, enverr = "USERPROFILE", "%userprofile%" 610 case "plan9": 611 env, enverr = "home", "$home" 612 } 613 if v := Getenv(env); v != "" { 614 return v, nil 615 } 616 // On some operating systems the home directory is not always defined. 617 switch runtime.GOOS { 618 case "android": 619 return "/sdcard", nil 620 case "ios": 621 return "/", nil 622 } 623 return "", errors.New(enverr + " is not defined") 624 } 625 626 // Chmod changes the mode of the named file to mode. 627 // If the file is a symbolic link, it changes the mode of the link's target. 628 // If there is an error, it will be of type [*PathError]. 629 // 630 // A different subset of the mode bits are used, depending on the 631 // operating system. 632 // 633 // On Unix, the mode's permission bits, [ModeSetuid], [ModeSetgid], and 634 // [ModeSticky] are used. 635 // 636 // On Windows, only the 0o200 bit (owner writable) of mode is used; it 637 // controls whether the file's read-only attribute is set or cleared. 638 // The other bits are currently unused. For compatibility with Go 1.12 639 // and earlier, use a non-zero mode. Use mode 0o400 for a read-only 640 // file and 0o600 for a readable+writable file. 641 // 642 // On Plan 9, the mode's permission bits, [ModeAppend], [ModeExclusive], 643 // and [ModeTemporary] are used. 644 func Chmod(name string, mode FileMode) error { return chmod(name, mode) } 645 646 // Chmod changes the mode of the file to mode. 647 // If there is an error, it will be of type [*PathError]. 648 func (f *File) Chmod(mode FileMode) error { return f.chmod(mode) } 649 650 // SetDeadline sets the read and write deadlines for a File. 651 // It is equivalent to calling both SetReadDeadline and SetWriteDeadline. 652 // 653 // Only some kinds of files support setting a deadline. Calls to SetDeadline 654 // for files that do not support deadlines will return ErrNoDeadline. 655 // On most systems ordinary files do not support deadlines, but pipes do. 656 // 657 // A deadline is an absolute time after which I/O operations fail with an 658 // error instead of blocking. The deadline applies to all future and pending 659 // I/O, not just the immediately following call to Read or Write. 660 // After a deadline has been exceeded, the connection can be refreshed 661 // by setting a deadline in the future. 662 // 663 // If the deadline is exceeded a call to Read or Write or to other I/O 664 // methods will return an error that wraps ErrDeadlineExceeded. 665 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 666 // That error implements the Timeout method, and calling the Timeout 667 // method will return true, but there are other possible errors for which 668 // the Timeout will return true even if the deadline has not been exceeded. 669 // 670 // An idle timeout can be implemented by repeatedly extending 671 // the deadline after successful Read or Write calls. 672 // 673 // A zero value for t means I/O operations will not time out. 674 func (f *File) SetDeadline(t time.Time) error { 675 return f.setDeadline(t) 676 } 677 678 // SetReadDeadline sets the deadline for future Read calls and any 679 // currently-blocked Read call. 680 // A zero value for t means Read will not time out. 681 // Not all files support setting deadlines; see SetDeadline. 682 func (f *File) SetReadDeadline(t time.Time) error { 683 return f.setReadDeadline(t) 684 } 685 686 // SetWriteDeadline sets the deadline for any future Write calls and any 687 // currently-blocked Write call. 688 // Even if Write times out, it may return n > 0, indicating that 689 // some of the data was successfully written. 690 // A zero value for t means Write will not time out. 691 // Not all files support setting deadlines; see SetDeadline. 692 func (f *File) SetWriteDeadline(t time.Time) error { 693 return f.setWriteDeadline(t) 694 } 695 696 // SyscallConn returns a raw file. 697 // This implements the syscall.Conn interface. 698 func (f *File) SyscallConn() (syscall.RawConn, error) { 699 if err := f.checkValid("SyscallConn"); err != nil { 700 return nil, err 701 } 702 return newRawConn(f) 703 } 704 705 // Fd returns the system file descriptor or handle referencing the open file. 706 // If f is closed, the descriptor becomes invalid. 707 // If f is garbage collected, a finalizer may close the descriptor, 708 // making it invalid; see [runtime.SetFinalizer] for more information on when 709 // a finalizer might be run. 710 // 711 // Do not close the returned descriptor; that could cause a later 712 // close of f to close an unrelated descriptor. 713 // 714 // Fd's behavior differs on some platforms: 715 // 716 // - On Unix and Windows, [File.SetDeadline] methods will stop working. 717 // - On Windows, the file descriptor will be disassociated from the 718 // Go runtime I/O completion port if there are no concurrent I/O 719 // operations on the file. 720 // 721 // For most uses prefer the f.SyscallConn method. 722 func (f *File) Fd() uintptr { 723 return f.fd() 724 } 725 726 // DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir. 727 // 728 // Note that DirFS("/prefix") only guarantees that the Open calls it makes to the 729 // operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the 730 // same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside 731 // the /prefix tree, then using DirFS does not stop the access any more than using 732 // os.Open does. Additionally, the root of the fs.FS returned for a relative path, 733 // DirFS("prefix"), will be affected by later calls to Chdir. DirFS is therefore not 734 // a general substitute for a chroot-style security mechanism when the directory tree 735 // contains arbitrary content. 736 // 737 // Use [Root.FS] to obtain a fs.FS that prevents escapes from the tree via symbolic links. 738 // 739 // The directory dir must not be "". 740 // 741 // The result implements [io/fs.StatFS], [io/fs.ReadFileFS], [io/fs.ReadDirFS], and 742 // [io/fs.ReadLinkFS]. 743 func DirFS(dir string) fs.FS { 744 return dirFS(dir) 745 } 746 747 var _ fs.StatFS = dirFS("") 748 var _ fs.ReadFileFS = dirFS("") 749 var _ fs.ReadDirFS = dirFS("") 750 var _ fs.ReadLinkFS = dirFS("") 751 752 type dirFS string 753 754 func (dir dirFS) Open(name string) (fs.File, error) { 755 fullname, err := dir.join(name) 756 if err != nil { 757 return nil, &PathError{Op: "open", Path: name, Err: err} 758 } 759 f, err := Open(fullname) 760 if err != nil { 761 // DirFS takes a string appropriate for GOOS, 762 // while the name argument here is always slash separated. 763 // dir.join will have mixed the two; undo that for 764 // error reporting. 765 err.(*PathError).Path = name 766 return nil, err 767 } 768 return f, nil 769 } 770 771 // The ReadFile method calls the [ReadFile] function for the file 772 // with the given name in the directory. The function provides 773 // robust handling for small files and special file systems. 774 // Through this method, dirFS implements [io/fs.ReadFileFS]. 775 func (dir dirFS) ReadFile(name string) ([]byte, error) { 776 fullname, err := dir.join(name) 777 if err != nil { 778 return nil, &PathError{Op: "readfile", Path: name, Err: err} 779 } 780 b, err := ReadFile(fullname) 781 if err != nil { 782 if e, ok := err.(*PathError); ok { 783 // See comment in dirFS.Open. 784 e.Path = name 785 } 786 return nil, err 787 } 788 return b, nil 789 } 790 791 // ReadDir reads the named directory, returning all its directory entries sorted 792 // by filename. Through this method, dirFS implements [io/fs.ReadDirFS]. 793 func (dir dirFS) ReadDir(name string) ([]DirEntry, error) { 794 fullname, err := dir.join(name) 795 if err != nil { 796 return nil, &PathError{Op: "readdir", Path: name, Err: err} 797 } 798 entries, err := ReadDir(fullname) 799 if err != nil { 800 if e, ok := err.(*PathError); ok { 801 // See comment in dirFS.Open. 802 e.Path = name 803 } 804 return nil, err 805 } 806 return entries, nil 807 } 808 809 func (dir dirFS) Stat(name string) (fs.FileInfo, error) { 810 fullname, err := dir.join(name) 811 if err != nil { 812 return nil, &PathError{Op: "stat", Path: name, Err: err} 813 } 814 f, err := Stat(fullname) 815 if err != nil { 816 // See comment in dirFS.Open. 817 err.(*PathError).Path = name 818 return nil, err 819 } 820 return f, nil 821 } 822 823 func (dir dirFS) Lstat(name string) (fs.FileInfo, error) { 824 fullname, err := dir.join(name) 825 if err != nil { 826 return nil, &PathError{Op: "lstat", Path: name, Err: err} 827 } 828 f, err := Lstat(fullname) 829 if err != nil { 830 // See comment in dirFS.Open. 831 err.(*PathError).Path = name 832 return nil, err 833 } 834 return f, nil 835 } 836 837 func (dir dirFS) ReadLink(name string) (string, error) { 838 fullname, err := dir.join(name) 839 if err != nil { 840 return "", &PathError{Op: "readlink", Path: name, Err: err} 841 } 842 return Readlink(fullname) 843 } 844 845 // join returns the path for name in dir. 846 func (dir dirFS) join(name string) (string, error) { 847 if dir == "" { 848 return "", errors.New("os: DirFS with empty root") 849 } 850 name, err := filepathlite.Localize(name) 851 if err != nil { 852 return "", ErrInvalid 853 } 854 if IsPathSeparator(dir[len(dir)-1]) { 855 return string(dir) + name, nil 856 } 857 return string(dir) + string(PathSeparator) + name, nil 858 } 859 860 // ReadFile reads the named file and returns the contents. 861 // A successful call returns err == nil, not err == EOF. 862 // Because ReadFile reads the whole file, it does not treat an EOF from Read 863 // as an error to be reported. 864 func ReadFile(name string) ([]byte, error) { 865 f, err := Open(name) 866 if err != nil { 867 return nil, err 868 } 869 defer f.Close() 870 871 return readFileContents(statOrZero(f), f.Read) 872 } 873 874 func statOrZero(f *File) int64 { 875 if fi, err := f.Stat(); err == nil { 876 return fi.Size() 877 } 878 return 0 879 } 880 881 // readFileContents reads the contents of a file using the provided read function 882 // (*os.File.Read, except in tests) one or more times, until an error is seen. 883 // 884 // The provided size is the stat size of the file, which might be 0 for a 885 // /proc-like file that doesn't report a size. 886 func readFileContents(statSize int64, read func([]byte) (int, error)) ([]byte, error) { 887 zeroSize := statSize == 0 888 889 // Figure out how big to make the initial slice. For files with known size 890 // that fit in memory, use that size + 1. Otherwise, use a small buffer and 891 // we'll grow. 892 var size int 893 if int64(int(statSize)) == statSize { 894 size = int(statSize) 895 } 896 size++ // one byte for final read at EOF 897 898 const minBuf = 512 899 // If a file claims a small size, read at least 512 bytes. In particular, 900 // files in Linux's /proc claim size 0 but then do not work right if read in 901 // small pieces, so an initial read of 1 byte would not work correctly. 902 if size < minBuf { 903 size = minBuf 904 } 905 906 data := make([]byte, 0, size) 907 for { 908 n, err := read(data[len(data):cap(data)]) 909 data = data[:len(data)+n] 910 if err != nil { 911 if err == io.EOF { 912 err = nil 913 } 914 return data, err 915 } 916 917 // If we're either out of capacity or if the file was a /proc-like zero 918 // sized file, grow the buffer. Per Issue 72080, we always want to issue 919 // Read calls on zero-length files with a non-tiny buffer size. 920 capRemain := cap(data) - len(data) 921 if capRemain == 0 || (zeroSize && capRemain < minBuf) { 922 data = slices.Grow(data, minBuf) 923 } 924 } 925 } 926 927 // WriteFile writes data to the named file, creating it if necessary. 928 // If the file does not exist, WriteFile creates it with permissions perm (before umask); 929 // otherwise WriteFile truncates it before writing, without changing permissions. 930 // Since WriteFile requires multiple system calls to complete, a failure mid-operation 931 // can leave the file in a partially written state. 932 func WriteFile(name string, data []byte, perm FileMode) error { 933 f, err := OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, perm) 934 if err != nil { 935 return err 936 } 937 _, err = f.Write(data) 938 if err1 := f.Close(); err1 != nil && err == nil { 939 err = err1 940 } 941 return err 942 } 943