Closed4

FoundationのFileManagerが投げる例外を調べる

nabeyangnabeyang

attributesOfItem(atPath path: String)

macOSやiOSの場合、例外を投げるのは、_lstatFile(atPath: path)からのみ、さらに見ると__fileSystemRepresentation(withPath: path)からと_NSErrorWithErrno(errno, reading: true, path: path)から投げることが分かる。

__fileSystemRepresentation(withPath: path)はCocoaError.fileReadInvalidFileNameを投げる。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager.swift#L1073
_NSErrorWithErrno(errno, reading: true, path: path)は、次のエラーが出る可能性があることが分かる。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FoundationErrors.swift#L175-L179
lstatのエラーはman 2 lstatで出てくる

     The fstat() system call will fail if:

     [EBADF]            fildes is not a valid open file descriptor.

     [EFAULT]           Sb points to an invalid address.

     [EIO]              An I/O error occurs while reading from or writing to the file system.

     The lstat() and stat() system calls will fail if:

     [EACCES]           Search permission is denied for a component of the path prefix.

     [EFAULT]           Sb or name points to an invalid address.

     [EIO]              An I/O error occurs while reading from or writing to the file system.

     [ELOOP]            Too many symbolic links are encountered in translating the pathname.  This is taken to be indicative of a looping symbolic link.

     [ELOOP]            If AT_SYMLINK_NOFOLLOW_ANY is passed and symbolic link was encountered during pathname resolution.

     [ENAMETOOLONG]     A component of a pathname exceeds {NAME_MAX} characters, or an entire path name exceeds {PATH_MAX} characters.

     [ENOENT]           The named file does not exist.

     [ENOTDIR]          A component of the path prefix is not a directory.

     The fstat(), lstat(), and stat() system calls will fail if:

     [EOVERFLOW]        The file size in bytes or the number of blocks allocated to the file or the file serial number cannot be represented correctly in the structure pointed to by buf.

     In addition to the errors returned by the stat() and lstat(), fstatat() may fail if:

     [EBADF]            The path argument does not specify an absolute path and the fd argument is neither AT_FDCWD nor a valid file descriptor open for searching.

     [EINVAL]           The value of the flag argument is not valid.

     [ENOTDIR]          The path argument is not an absolute path and fd is neither AT_FDCWD nor a file descriptor associated with a directory.

いずれもdomainはNSCocoaErrorDomainみたい。

nabeyangnabeyang

createDirectory(at url: URL, withIntermediateDirectories createIntermediates: Bool, attributes: [FileAttributeKey : Any]? = [:])

urlがファイルパスでなければ.fileWriteUnsupportedSchemeを投げる。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager.swift#L328

処理の本体は次の箇所
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager%2BPOSIX.swift#L365-L400

ファイルパスがあまりにも長いと__fileSystemRepresentation(withPath: path)でCocoaError.fileReadInvalidFileNameを投げる。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager.swift#L1073

mkdirに失敗するとthrow _NSErrorWithErrno(posixError, reading: false, path: path)を投げる。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FoundationErrors.swift#L183-L193

EEXISTは確実に呼ばれる可能性がある。
mkdirのerrnoは(man 2 mkdir)


     [EACCES]           Search permission is denied for a component of the path prefix.

     [EACCES]           Write permission is denied for the parent directory.

     [EDQUOT]           The new directory cannot be created because the user's quota of disk blocks on the file system that will contain the directory has been exhausted.

     [EDQUOT]           The user's quota of inodes on the file system on which the directory is being created has been exhausted.

     [EEXIST]           The named file exists.

     [EFAULT]           Path points outside the process's allocated address space.

     [EIO]              An I/O error occurred while making the directory entry or allocating the inode.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

     [EISDIR]           The named file is the root directory.

     [ELOOP]            Too many symbolic links were encountered in translating the pathname.  This is taken to be indicative of a looping symbolic link.

     [EMLINK]           The parent directory already has {LINK_MAX} links.

     [ENAMETOOLONG]     A component of a pathname exceeded {NAME_MAX} characters, or an entire path name exceeded {PATH_MAX} characters.

     [ENOENT]           A component of the path prefix does not exist or path is an empty string.

     [ENOSPC]           The new directory cannot be created because there is no space left on the file system that would contain it.

     [ENOSPC]           There are no free inodes on the file system on which the directory is being created.

     [ENOTDIR]          A component of the path prefix is not a directory.

     [EROFS]            The parent directory resides on a read-only file system.

     In addition to the errors returned by the mkdir(), the mkdirat() function may fail if:

     [EBADF]            The path argument does not specify an absolute path and the fd argument is neither AT_FDCWD nor a valid file descriptor open for searching.

     [ENOTDIR]          The path argument is not an absolute path and fd is neither AT_FDCWD nor a file descriptor associated with a directory.

     [EILSEQ]           The filename does not match the encoding rules.

setAttributesでは、chmodが呼ばれ、errnoがセットされるとthrow _NSErrorWithErrno(posixError, reading: false, path: path)が投げられる。chmodのerrnoは次の通り。

     [EACCES]           Search permission is denied for a component of the path prefix.

     [EFAULT]           Path points outside the process's allocated address space.

     [EINTR]            Its execution was interrupted by a signal.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

     [ELOOP]            Too many symbolic links were encountered in translating the pathname.  This is taken to be indicative of a looping symbolic link.

     [ELOOP]            If AT_SYMLINK_NOFOLLOW_ANY was passed and a symbolic link was encountered in translating the pathname.

     [ENAMETOOLONG]     A component of a pathname exceeded {NAME_MAX} characters, or an entire path name exceeded {PATH_MAX} characters.

     [ENOENT]           The named file does not exist.

     [ENOTDIR]          A component of the path prefix is not a directory.

     [EPERM]            The effective user ID does not match the owner of the file and the effective user ID is not the super-user.

     [EROFS]            The named file resides on a read-only file system.

     fchmod() will fail if:

     [EBADF]            fildes is not a valid file descriptor.

     [EINVAL]           fildes refers to a socket, not to a file.

     [EINVAL]           mode is not a valid file mode.

     [EINTR]            Its execution was interrupted by a signal.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

     [EPERM]            The effective user ID does not match the owner of the file and the effective user ID is not the super-user.

     [EROFS]            The file resides on a read-only file system.

     In addition to the chmod() errors, fchmodat() fails if:

     [EBADF]            The path argument does not specify an absolute path and the fd argument is neither AT_FDCWD nor a valid file descriptor open for searching.

     [EINVAL]           The value of the flag argument is not valid.

     [ENOTDIR]          The path argument is not an absolute path and fd is neither AT_FDCWD nor a file descriptor associated with a directory.

setAttributesで、特定のattributeをセットするとCocoaError.fileWriteUnknownを投げる
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager.swift#L442-L450
setAttributeでも_lstatFileが呼ばれる
また、chflagsが失敗するとエラーを投げる。chflagsのerrnoは次の通り

     [ENOTDIR]          A component of the path prefix is not a directory.

     [ENAMETOOLONG]     A component of a pathname exceeded {NAME_MAX} characters, or an entire path name exceeded {PATH_MAX} characters.

     [ENOENT]           The named file does not exist.

     [EACCES]           Search permission is denied for a component of the path prefix.

     [ELOOP]            Too many symbolic links were encountered in translating the pathname.

     [EPERM]            The effective user ID does not match the owner of the file and the effective user ID is not the super-user.

     [EROFS]            The named file resides on a read-only file system.

     [EFAULT]           Path points outside the process's allocated address space.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

     [ENOTSUP]          The operation isn't supported by the filesystem.

     fchflags() will fail if:

     [EBADF]            The descriptor is not valid.

     [EINVAL]           fd refers to a socket, not to a file.

     [EPERM]            The effective user ID does not match the owner of the file and the effective user ID is not the super-user.

     [EROFS]            The file resides on a read-only file system.

     [EIO]              An I/O error occurred while reading from or writing to the file system.

     [ENOTSUP]          The operation isn't supported by the filesystem.

_updateTimesでutimesが失敗しても例外が投げられる。


     [EACCES]           Search permission is denied for a component of the path prefix; or the times argument is NULL and the effective user ID of the process does not match the owner of the
                        file, and is not the super-user, and write access is denied.

     [EFAULT]           path or times points outside the process's allocated address space.

     [EIO]              An I/O error occurs while reading or writing the affected inode.

     [ELOOP]            Too many symbolic links are encountered in translating the pathname.  This is taken to be indicative of a looping symbolic link.

     [ENAMETOOLONG]     A component of a pathname exceeds NAME_MAX characters, or an entire path name exceeded PATH_MAX characters.

     [ENOENT]           The named file does not exist.

     [ENOTDIR]          A component of the path prefix is not a directory.

     [EPERM]            The times argument is not NULL and the calling process's effective user ID does not match the owner of the file and is not the super-user.

     [EROFS]            The file system containing the file is mounted read-only.

     The futimes() system call will fail if:

     [EBADF]            fildes does not refer to a valid descriptor.

     All of the functions will fail if:

     [EACCES]           The times argument is NULL and the effective user ID of the process does not match the owner of the file, and is not the super-user, and write access is denied.

     [EFAULT]           times points outside the process's allocated address space.

     [EIO]              An I/O error occurred while reading or writing the affected inode.

     [EPERM]            The times argument is not NULL and the calling process's effective user ID does not match the owner of the file and is not the super-user.

     [EROFS]            The file system containing the file is mounted read-only.
nabeyangnabeyang

removeItem(at: URL)

urlがファイルURLではない場合はCocoaError.fileWriteUnsupportedSchemeを投げる。
_fileSystemRepresentation(withPath: path, block)でファイルパスが長ければ、CocoaError.fileReadInvalidFileNameを投げる。
rmdirしたときENOTEMPTYENOTDIR以外であれば、_NSErrorWithErrno(errno, reading: false, path: path)を投げる。unlinkに失敗した時も_NSErrorWithErrno(errno, reading: false, path: path)を投げる。
次の箇所で例外が投げられているfts_readの状態が関係している。
https://github.com/apple/swift-corelibs-foundation/blob/swift-DEVELOPMENT-SNAPSHOT-2022-11-19-a/Sources/Foundation/FileManager%2BPOSIX.swift#L762-L781
fts_infoの定義(man 3 fts_read)

     fts_info     One of the following values describing the returned FTSENT structure and the file it represents.  With the exception of directories without errors (FTS_D), all of these
                  entries are terminal, that is, they will not be revisited, nor will any of their descendants be visited.

                  FTS_D        A directory being visited in pre-order.

                  FTS_DC       A directory that causes a cycle in the tree.  (The fts_cycle field of the FTSENT structure will be filled in as well.)

                  FTS_DEFAULT  Any FTSENT structure that represents a file type not explicitly described by one of the other fts_info values.

                  FTS_DNR      A directory which cannot be read.  This is an error return, and the fts_errno field will be set to indicate what caused the error.

                  FTS_DOT      A file named ‘.’ or ‘..’ which was not specified as a file name to fts_open() or fts_open_b() (see FTS_SEEDOT).

                  FTS_DP       A directory being visited in post-order.  The contents of the FTSENT structure will be unchanged from when it was returned in pre-order, i.e. with the fts_info
                               field set to FTS_D.

                  FTS_ERR      This is an error return, and the fts_errno field will be set to indicate what caused the error.

                  FTS_F        A regular file.

                  FTS_NS       A file for which no stat(2) information was available.  The contents of the fts_statp field are undefined.  This is an error return, and the fts_errno field
                               will be set to indicate what caused the error.

                  FTS_NSOK     A file for which no stat(2) information was requested.  The contents of the fts_statp field are undefined.

                  FTS_SL       A symbolic link.

                  FTS_SLNONE   A symbolic link with a non-existent target.  The contents of the fts_statp field reference the file characteristic information for the symbolic link itself.
このスクラップは2023/06/10にクローズされました