In my attempts to figure out some problems I've been having I had to learn more about fs_usage. I don't see this information posted anywhere else, so here it is.
I usually use fs_usage like this.
fs_usage -w | grep /path
fs_usage -w | egrep /.*process
To date, I've had no reason to care about system calls that don't involve files. Since I'm mostly interested in trying to figure out what Apple processes are doing, I have to throw a wide net and capture a multitude of processes, which is why I use grep instead of limiting to a process.
Running fs_usage generates a ton of data. It helps to understand the data a little bit so you know what you are looking for.
fs_usage statistics: System calls
I ran fs_usage while creating a user in System Preferences and I made a list of the most common system calls that showed up. Here's a description of them.
- 2471 getattrlist - The getattrlist() function returns attributes (that is, metadata) of file system objects.
- 793 lstat64 - lstat() returns information about the link
- 255 fsgetpath - The fsgetpath() function returns the path... associated with a filesystem object...
- 235 stat64 - The stat() function obtains information about the file pointed to by path.
- 228 open - open or create a file for reading or writing
- 186 listxattr - list extended attribute names
- 137 chmod - change mode of file
- 130 fstatat64 - a more general interface for accessing file information
- 127 lchown - similar to chown() but does not follow symbolic links.
- 109 statfs64 - The statfs() routine returns information about a mounted file system.
- 71 utimes - set file access and modification times
- 55 mkdir - make a directory file
- 47 chflags - set file flags
- 39 chmod_extended - Change the mode of a file given a path name; with extended argument list (including extended security (ACL)).
- 36 mkdirat - make a directory file
- 34 symlink - make symbolic link to a file
- 34 chown - change owner and group of a file
- 31 access - check accessibility of a file
- 27 rename - change the name of a file
- 25 openat - open or create a file for reading or writing
- 15 guarded_open_np
- 14 setxattr - set an extended attribute value
- 11 guarded_open_dpro
- 10 unlink - remove directory entry
- 6 readlink - read value of a symbolic link
- 3 open_dprotected
- 2 getxattr - get an extended attribute value
- 2 chmodat - Change mode of a file given a path name.
- 1 rmdir - remove a directory file
- 1 removexattr - remove an extended attribute value
Here's the system calls that actually change something on disk.
- chmod, chmodat, chmod_extended
- chown, lchown
- mkdir, mkdirat
- open, openat, open_dprotected, guarded_open_dpro, guarded_open_np (see below for flags)
The open system call change files if it has the "W", "C", "A", or "T" flags. I had to read the fs_usage source code to find out exactly what flags the fs_usage letters meant. Here they are.
- R - O_RDONLY, open for reading only
- W - O_WRONLY, open for writing only
- RW - O_RDWR, open for reading and writing
- C - O_CREAT, create file if it does not exist
- A - O_APPEND, append on each write
- T - O_TRUNC, truncate size to 0
- E - O_EXCL, error if O_CREAT and the file exists
- N - O_NONBLOCK, do not block on open or for data to become available
- l - O_SHLOCK & ! O_EXLOCK, atomically obtain a shared lock
- L - O_SHLOCK & O_EXLOCK, atomically obtain an exclusive lock
- F - O_NOFOLLOW, do not follow symlinks
- S - O_SYMLINK, allow open of symlinks
- V - O_EVTONLY, descriptor requested for event notifications only
- X - O_CLOEXEC, mark as close-on-exec
I'm pretty sure that when data is actually written to disk you'll see something like this.
14:48:08.219356 WrData[A] D=0x001ce0c4 B=0x1000 /dev/disk2s5 /path/to/file/.BC.T_w6qwGY 0.000272 W ditto.5145
A number in brackets ("[ 2]") means there was an error when the syscall ran. Here is a list of the error numbers and this has a description of most errors (the other errors I had to look up in Apple's GitHub repository). Here are the errors I saw when running fs_usage.
- 1 - EPERM, operation not permitted (this is a generic error, e.g. creating a directory hard link, chmod resource forks, setting an xattr name that's too long, etc)
- 2 - ENOENT, O_CREAT is not set and the named file does not exist.
- 13 - EACCES, permission denied
- 17 - EEXIST, O_CREAT and O_EXCL are specified and the file exists.
- 22 - EINVAL, the value of oflag is not valid.
- 93 - ENOATTR, the extended attribute does not exist.
File (directory) doesn't exist example.
14:48:07.350811 stat64 [ 2] /Users/test 0.000034 com.apple.preferences.users.remo.4460
Sometimes there was a negative number in brackets that appeared right before the path. I don't know what that meant.
14:48:08.148395 mkdirat [-2]//Users/test 0.000064 DirectoryTools.5135
This example includes a file doesn't exist error as well.
14:48:08.152561 fstatat64 [ 2] [-2]//Users/test/Music/.BC.T_dJrTAJ 0.000004 ditto.5138
The number following the process name is the thread number.
I'm pretty sure that some system calls are hidden from users unless they disable SIPS. You'd mainly be interested in seeing these system calls if you're debugging Hackintoshes or reverse engineering other "protected" Apple processes like DRM.
This is part of dtrace. I've heard
opensnoop is an alternative to fs_usage. I never learned how to use dtrace effectively so I can't help you with this. I think
opensnoop (and dtrace in general) is able to filter down the information much better than fs_usage.
Published: 2022-08-03, last edited: 2022-08-03
Copyright © 2022 James Reynolds