/etc/rawhide.conf
- configuration file for rh(1)
The /etc/rawhide.conf
file (or similar) contains a standard library of functions that can be used by all users of rh(1). It is the first file read by rh(1). Any files in the /etc/rawhide.conf.d
directory (or similar) whose names do not start with dot ("."
) are then read (in lexicographic order), and can contain additional system-wide function definitions.
User-specific configuration is then read from the ~/.rhrc
and ~/.rhrc.d/*
files in the same manner.
Any files specified by rh(1)'s -f
option are then read, followed by the contents of rh(1)'s -e
option argument, which can also contain additional function definitions, and a trailing file test expression.
All of these share the same syntax.
The location of the system-wide configuration might be somewhere else, depending on the operating system preferences (e.g., /usr/local/etc
, /opt/local/etc
, /usr/pkg/etc
).
The output of rh --help
states where the system-wide configuration files are on the local system.
The following subsections describe the syntax and semantics of rawhide search criteria source/configuration files.
Every rawhide source/configuration file consists of zero or more function definitions, optionally followed by a file test expression, which is optionally terminated by a semicolon (";"
).
If a source file does contain a trailing file test expression, that expression becomes the default file test expression, unless another file read later also contains a trailing file test expression, in which case, that expression becomes the default file test expression. It is not expected that any system-wide or user-specific configuration files will contain a trailing file test expression, but they can.
Files specified with the -f
option are more likely to contain a trailing file test expression, in which case, there is no need for the -e
option (explicit or implicit). But if the -e
option is also supplied, then any file test expression that it specifies takes precedence.
Technically, even the -e
option argument does not require a file test expression (because there is a default which matches everything), but it will usually supply one.
Search criteria can include explanations in the form of comments. There are three comment styles:
/* C-style comments */
These comments start with /*
and end with */
and can span multiple lines.
// C++-style comments
These comments start with //
and end at the end of the line.
# Shell-style comments
These comments start with #
and end at the end of the line.
The rawhide search criteria language is like a tiny subset of the C language's expression syntax, with a few domain-specific additions. All of C's conditional, logical, relational, equality, arithmetic, and bit operators are available. But the only type is integer. There are special tokens to represent various things, some built-in symbols, and user-defined functions.
Here is the grammar of the search criteria language (BNF with a few liberties taken):
<program> ::=
<function-list> <expression> ";" EOF
| <function-list> <expression> EOF
| <function-list> EOF
<function-list> ::=
<function> <function-list>
| EMPTY
<function> ::=
IDENTIFIER <parameters> "{" <return> <expression> <eos> "}"
<return> ::=
"return"
| EMPTY
<eos> == >
";"
| EMPTY
<parameters> ::=
"(" <id-list> ")"
| "(" ")"
| EMPTY
<id-list> ::=
IDENTIFIER <id-tail>
<id-tail> ::=
"," <id-list>
| EMPTY
<expression> ::= <or> "?" <expression> ":" <expression> | <or>
<or> ::= <and> "||" <or> | <and>
<and> ::= <bitor> "&&" <and> | <bitor>
<bitor> ::= <bitxor> "|" <bitor> | <bitxor>
<bitxor> ::= <bitand> "^" <bitxor> | <bitand>
<bitand> ::= <eq> "&" <bitand> | <eq>
<eq> ::= <rel> <eq-op> <rel> | <rel>
<eq-op> ::= "==" | "!="
<rel> ::= <shift> <rel-op> <shift> | <shift>
<rel-op> ::= "<" | ">" | "<=" | ">="
<shift> ::= <add> <shift-op> <shift> | <add>
<shift-op> ::= "<<" | ">>"
<add> ::= <mul> <add-op> <add> | <mul>
<add-op> ::= "+" | "-"
<mul> ::= <unary> <mul-op> <mul> | <unary>
<mul-op> ::= "*" | "/" | "%"
<unary> ::= <unary-op> <unary> | <factor>
<unary-op> ::= "-" | "~" | "!"
<factor> ::=
<number>
| <user-id>
| <group-id>
| "[" <date-time> "]"
| <pattern>
| <reference-file>
| <built-in>
| <function-call>
| <parameter>
| "(" <expression> ")"
<number> ::=
DECIMAL
| DECIMAL NOSPACE <scale>
| "0" NOSPACE OCTAL
| "0x" NOSPACE HEXADECIMAL
<scale> ::=
"K" | "M" | "G" | "T" | "P" | "E"
| "k" | "m" | "g" | "t" | "p" | "e"
<user-id> ::=
"$" NOSPACE USERNAME
| "$$"
<group-id> ::=
"@" NOSPACE GROUPNAME
| "@@"
<date-time> ::=
DECIMAL "/" DECIMAL "/" DECIMAL
| DECIMAL "/" DECIMAL "/" DECIMAL DECIMAL
| DECIMAL "/" DECIMAL "/" DECIMAL DECIMAL ":" DECIMAL
| DECIMAL "/" DECIMAL "/" DECIMAL DECIMAL ":" DECIMAL ":" DECIMAL
<pattern> ::=
STRING
| STRING NOSPACE "." NOSPACE <pattern-modifier>
<pattern-modifier> ::=
"i" | "re" | "rei"
| "path" | "ipath" | "repath" | "reipath"
| "link" | "ilink | "relink" | "reilink"
| "body" | "ibody | "rebody" | "reibody"
| "what" | "iwhat | "rewhat" | "reiwhat"
| "mime" | "imime | "remime" | "reimime"
| "acl" | "iacl" | "reacl" | "reiacl"
| "ea" | "iea" | "reea" | "reiea"
| "sh"
<reference-file> ::=
STRING NOSPACE "." NOSPACE <reference-file-field>
<reference-file-field> ::=
"exists" | "dev" | "major" | "minor" | "ino"
| "mode" | "type" | "perm" | "nlink" | "uid"
| "gid" | "rdev" | "rmajor" | "rminor" | "size"
| "blksize" | "blocks" | "atime" | "mtime" | "ctime"
| "attr" | "proj" | "gen" | "strlen" | "inode"
| "nlinks" | "user" | "group" | "sz" | "accessed"
| "modified" | "changed" | "attribute" | "project" | "generation"
| "len"
<built-in> ::=
"dev" | "major" | "minor" | "ino" | "mode"
| "nlink" | "uid" | "gid" | "rdev" | "rmajor"
| "rminor" | "size" | "blksize" | "blocks" | "atime"
| "mtime" | "ctime" | "attr" | "proj" | "gen"
| "nouser" | "nogroup" | "readable" | "writable" | "executable"
| "strlen" | "depth" | "prune" | "trim" | "exit"
| "now" | "today" | "second" | "minute" | "hour"
| "day" | "week" | "month" | "year" | "IFREG"
| "IFDIR" | "IFLNK" | "IFCHR" | "IFBLK" | "IFSOCK"
| "IFIFO" | "IFDOOR" | "IFMT" | "ISUID" | "ISGID"
| "ISVTX" | "IRWXU" | "IRUSR" | "IWUSR" | "IXUSR"
| "IRWXG" | "IRGRP" | "IWGRP" | "IXGRP" | "IRWXO"
| "IROTH" | "IWOTH" | "IXOTH" | "texists" | "tdev"
| "tmajor" | "tminor" | "tino" | "tmode" | "tnlink"
| "tuid" | "tgid" | "trdev" | "trmajor" | "trminor"
| "tsize" | "tblksize" | "tblocks" | "tatime" | "tmtime"
| "tctime" | "tstrlen"
<function-call> ::=
IDENTIFIER <arguments>
<arguments> ::=
"(" <expr-list> ")"
| "(" ")"
| EMPTY
<expr-list> ::=
<expression> <expr-tail>
<expr-tail> ::=
"," <expr-list>
| EMPTY
<parameter> ::=
IDENTIFIER
The following C operators are available (presented in groups of increasing precedence):
?: Conditional (i.e., condition-expr ? if-expr : else-expr)
|| Logical or
&& Logical and
| Bit or
^ Bit exclusive or
& Bit and
== Equals
!= Not equals
< Less than
> Greater than
<= Less than or equal to
>= Greater than or equal to
<< Bit shift left
>> Bit shift right
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo (remainder)
- Minus (unary)
~ Bit not (unary)
! Logical not (unary)
Parentheses override operator precedence (e.g., (1 + 2) * 3
).
Like in C, the ?:
and ||
and &&
operators use "short-circuit" evaluation.
With the ternary conditional operator (?:
), the second operand is only evaluated when the first operand evaluates to true (i.e., non-zero), and the third operand is only evaluated when the first operand evaluates to false (i.e., zero).
With the logical or operator (||
), the second operand is only evaluated when the first operand evaluates to false. Otherwise, it is not necessary.
With the logical and operator (&&
), the second operand is only evaluated when the first operand evaluates to true. Otherwise, it is not necessary.
This matters when using the prune
, trim
, or exit
built-ins (see below), because they have control flow side-effects when they are evaluated. It is also important when using the texists
built-in, the sh
"pattern" modifier, and the exists
reference file field (see below).
All the other binary operators always evaluate both operands.
Numeric constants can be decimal, octal (starting with 0
), or hexadecimal (starting with 0x
). All numbers are integers. And everything is a number.
Decimal numbers can have a suffix letter that indicates the scale (e.g., 10K
), in units based on 1024 (upper case), or based on 1000 (lower case):
K = Kibibytes (KiB, units of 1024)
M = Mebibytes (MiB, units of 1024^2)
G = Gibibytes (GiB, units of 1024^3)
T = Tebibytes (TiB, units of 1024^4)
P = Pebibytes (PiB, units of 1024^5)
E = Exbibytes (EiB, units of 1024^6)
k = Kilobytes (KB, units of 1000)
m = Megabytes (MB, units of 1000^2)
g = Gigabytes (GB, units of 1000^3)
t = Terabytes (TB, units of 1000^4)
p = Petabytes (PB, units of 1000^5)
e = Exabytes (EB, units of 1000^6)
String literals are enclosed in double quotes ("""
). Any double quote characters in the string must be quoted with a preceding backslash character ("\"
). Backslashes can also be quoted with a preceding backslash. Any backslashes that do not precede a double quote or another backslash are treated as normal characters, and are included in the string.
Strings usually contain a pattern to match against file names (or certain other information associated with files). The value of a pattern string is whether or not the pattern match succeeded. Strings can also contain a shell command to execute. The value of a shell command string is the exit success status of the command. See the Pattern matching and Pattern modifiers sections below for details. Strings can also contain the path of a reference file to use for comparison purposes. See the Reference file fields section below for details.
A token starting with a dollar sign ("$"
) immediately followed by a user name evaluates to that user's user ID. It is assumed that user names consist entirely of letters, digits, and dot ("."
), dash ("-"
), and underscore characters ("_"
). All non-ASCII characters (UTF-8 or ISO-8859-*) are considered to be "letters".
The token $$
evaluates to the current user's user ID.
A token starting with an at sign ("@"
) immediately followed by a group name evaluates to that group's group ID. It is assumed that group names consist entirely of letters, digits, and dot ("."
), dash ("-"
), and underscore characters ("_"
). All non-ASCII characters (UTF-8 or ISO-8859-*) are considered to be "letters".
The token @@
evaluates to the current user's primary group ID.
Dates and date/times can be specified between square brackets ("[]"
) (i.e., [
YYYY/
MM/
DD]
and [
YYYY/
MM/
DD hh:
mm:
ss]
). They are interpreted as being in the local time zone. If the year is specified as a number below 100, then it is interpreted as being a year in the current century. Hours must be in 24-hour time, not 12-hour time. The seconds component is optional if it is zero (i.e., [
YYYY/
MM/
DD hh:
mm]
). The minutes component is also optional if both it and the seconds are zero (i.e., [
YYYY/
MM/
DD hh]
). The hours component is also optional if it and the minutes and seconds are all zero (i.e., midnight). Then, it's just a date. Dates and date/times evaluate to the corresponding number of seconds since the UNIX epoch.
Note that if the month, day, hours, minutes, or seconds are outside their valid ranges, the date or date/time is normalized so that, for example, the 40th of October is interpreted as the 9th of November, and the time 25:90:90
is interpreted as 2:31:30
the following day. See mktime(3) for details.
Functions can be defined to give names to expressions, and to make those names available for use in subsequent expressions. Function names can't be the same as the names of any existing functions or built-in symbols.
f() { return expr; }
Functions can only contain a return statement or expression. The return
keyword and semicolon (";"
) are optional.
f() { expr }
Functions can have parameters. Parameter names can't be the same as the names of any existing functions or built-in symbols.
f(x, y, z) { (x + y) * z }
Functions with no parameters can be defined and called with or without parentheses.
f() { expr }
g { f }
g()
A function can only be called if its definition has already been encountered by the parser. So recursive functions are possible, but mutually recursive functions are not.
The names of functions and parameters must start with a letter or underscore character ("_"
), which can be followed by letters, underscores, and digits. All non-ASCII characters (UTF-8 or ISO-8859-*) are considered to be "letters".
There are various built-in symbols representing inode metadata (i.e., stat(2) structure fields), constants, and other useful information.
dev
The device number of the device/filesystem that the current candidate file resides on. This is the st_dev
field of the corresponding stat(2) structure. See the related major
and minor
built-ins (next) for extracting the major and minor device numbers from dev
.
major
The major device number of the device/filesystem that the current candidate file resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
minor
The minor device number of the device/filesystem that the current candidate file resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
ino
The inode number of the current candidate file. This is the st_ino
field of the corresponding stat(2) structure.
mode
The mode of the current candidate file. This is the st_mode
field of the corresponding stat(2) structure. This contains the file type and permissions. The standard library provides the type
and perm
functions (among others) for extracting the file type and permissions from mode
.
nlink
The number of hard links to the current candidate file. This is the st_nlink
field of the corresponding stat(2) structure.
uid
The user ID of the owner of the current candidate file. This is the st_uid
field of the corresponding stat(2) structure.
gid
The group ID of the group of the current candidate file. This is the st_gid
field of the corresponding stat(2) structure.
rdev
The device number of the current candidate file. This is the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices. See the related rmajor
and rminor
built-ins (next) for extracting the major and minor device numbers from rdev
.
rmajor
The major device number of the current candidate file. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
rminor
The minor device number of the current candidate file. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
size
The size in bytes of the current candidate file. This is the st_size
field of the corresponding stat(2) structure.
For candidate symlinks (that are not followed with the -y
or -Y
option), this is the length in bytes of the target path.
For candidate directories that are readable, this is not the st_size
field of the corresponding stat(2) structure. Instead, this is the number of entries it contains (excluding .
and ..
).
For candidate directories that are unreadable (and everything else), this is the usual (undocumented) st_size
field of the corresponding stat(2) structure.
blksize
The preferred block size for efficient I/O on the current candidate file's filesystem. This is the st_blksize
field of the corresponding stat(2) structure. On some filesystems (e.g., zfs), this is specific to each file, rather than to the whole filesystem.
Note that this is unrelated to the blocks
built-in (see next).
blocks
The number of 512-byte blocks occupied by the current candidate file. This is the st_blocks
field of the corresponding stat(2) structure.
atime
The time that the current candidate file was last accessed. This is the st_atime
field of the corresponding stat(2) structure.
mtime
The time that the current candidate file's contents were last modified. This is the st_mtime
field of the corresponding stat(2) structure.
ctime
The time that the current candidate file's inode was last changed. This is the st_ctime
field of the corresponding stat(2) structure.
attr
On Linux, the current candidate file's ext2-style file attribute bit mask. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details. See /etc/rawhide.conf.d/attributes
for all the related predicate functions (e.g., immutable
, append
, nodump
, nocow
, dax
, ...).
Note: If the current candidate file is a symlink, it is never followed for the purpose of obtaining the file attributes. This is a decision made by libe2p. This is not affected by the -y
or -Y
options. Also note that symlinks do not have their own file attributes (i.e., attr
is zero).
On Linux, this is only available on systems with libe2p. On Linux systems without libe2p, this is not a built-in symbol. Instead, this is a place-holder function that returns zero.
This is also available on FreeBSD, OpenBSD, NetBSD, and macOS. The attributes/flags that are available vary from system to system. See chflags(1) for details. See /etc/rawhide.conf.d/attributes
for all the related predicate functions (e.g., uimmutable
, uappend
, nodump
, opaque
, ...).
On other systems, this doesn't exist at all.
proj
On Linux, the current candidate file's ext2-style file project number. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details.
Note: If the current candidate file is a symlink, it is always followed for the purpose of obtaining the file project. This is not affected by the -y
or -Y
options.
Note: This is only available on Linux systems with libe2p. On Linux systems without libe2p, this is not a built-in symbol. Instead, this is a place-holder function that returns zero. On other systems, this doesn't exist at all.
gen
On Linux, the current candidate file's ext2-style version/generation number. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details.
Note: If the current candidate file is a symlink, it is always followed for the purpose of obtaining the file version/generation. This is not affected by the -y
or -Y
options.
Note: This is only available on Linux systems with libe2p. On Linux systems without libe2p, this is not a built-in symbol. Instead, this is a place-holder function that returns zero. On other systems, this doesn't exist at all.
nouser
This is true (i.e., non-zero) when the current candidate file's uid
does not correspond to any user in the user database (e.g., the local password file /etc/passwd
, NIS, and LDAP).
nogroup
This is true (i.e., non-zero) when the current candidate file's gid
does not correspond to any group in the group database (e.g., the local group file /etc/group
, NIS, and LDAP).
readable
This is true (i.e., non-zero) when the current candidate file is readable by the current user. This uses the access(2) system call, rather than the file permissions.
writable
This is true (i.e., non-zero) when the current candidate file is writable by the current user. This uses the access(2) system call, rather than the file permissions.
executable
This is true (i.e., non-zero) when the current candidate file is executable by the current user. This uses the access(2) system call, rather than the file permissions.
strlen
This is the length in bytes of the base name of the current candidate file. Note that this is zero for the root directory (/
) which has no base name.
depth
This is the depth of the current candidate file relative to the starting search directory. The starting search directory itself has depth 0
. Its children have depth 1
, and so on.
prune
This always evaluates to true (i.e., non-zero), and as a side-effect, causes the directory tree being searched to be "pruned". This means that the current candidate file will not match, and if it is a directory, it will not be searched. This can be used to speed up a search.
prune
needs to be used with the ?:
or ||
or &&
operator (see above) to conditionally skip part of a directory tree and search the rest.
prune
and the -D
(depth-first) option are incompatible. When the -D
option is used, prune
will not work. It will not prevent searching below the current candidate path. The same applies to the -U
(unlink) option, which implies the -D
option.
Note: This is counter-intuitive. prune
evaluates to true, even though it effectively causes the file test expression as a whole to evaluate to false (i.e., zero), in order to prevent the current candidate file from matching. The reason that prune
evaluates to true rather than false, is to make it possible to have expressions like (bad && prune || good)
as a syntactic alternative to (bad ? prune : good)
.
Note: The prune
and trim
built-ins are very similar (see next). They both prevent searching below the current candidate path. The only difference between them is whether or not the current candidate path itself is also prevented from matching. Use prune
when the current candidate path needs to be excluded. Use trim
when it needs to be included. You can think of prune
as a heavy trim
.
trim
This always evaluates to true (i.e., non-zero), and as a side-effect, causes the directory tree being searched to be "trimmed". This means that if the current candidate file is a directory, it will not be searched (like prune
). Unlike prune
, the current candidate file itself is not prevented from matching. So this has no side-effect when the current candidate file is not a directory. This can be used to speed up a search.
trim
needs to be used with the ?:
or ||
or &&
operator (see above) to conditionally skip part of a directory tree and search the rest.
trim
and the -D
(depth-first) option are incompatible. When the -D
option is used, trim
will not work. It will not prevent searching below the current candidate path. The same applies to the -U
(unlink) option, which implies the -D
option.
Note: The trim
and prune
built-ins are very similar (see above). They both prevent searching below the current candidate path. The only difference between them is whether or not the current candidate path itself is also prevented from matching. Use trim
when the current candidate path needs to be included. Use prune
when it needs to be excluded. You can think of trim
as a light prune
.
exit
This always evaluates to true (i.e., non-zero), and as a side-effect, causes the search to terminate immediately after the current candidate file. This can be used to find the first matching file, and then stop.
exit
needs to be used with the ?:
or ||
or &&
operator (see above) to conditionally terminate the search.
exit
can be used in combination with prune
and/or trim
(see above) (e.g., bad && prune || good && exit
).
now
The current time (when rh(1) started) in seconds since the UNIX epoch.
today
The time last midnight (local time) in seconds since the UNIX epoch.
second
The value 1
.
minute
The number of seconds in a minute.
hour
The number of seconds in an hour.
day
The number of seconds in a day.
week
The number of seconds in a week.
month
The average number of seconds in a month.
year
The average number of seconds in a year.
IFMT
The same as the S_IFMT
bit mask from C's <sys/stat.h>
header file. This bit mask represents the bits in the mode
that represent the file type. The file type is (mode & IFMT
) (see next), and the file permissions are (mode & ~IFMT)
(see below).
IFREG
, IFDIR
, IFLNK
, IFCHR
, IFBLK
, IFSOCK
, IFIFO
, IFDOOR
The same as the corresponding "S_"
values from C's <sys/stat.h>
header file. These values correspond to the different types of filesystem entry (i.e., regular file, directory, symbolic link, character device, block device, socket, fifo/pipe, and door, respectively). IFDOOR
only applies to Solaris.
ISUID
, ISGID
, ISVTX
The same as the corresponding "S_"
bit masks from C's <sys/stat.h>
header file. These bit masks correspond to the setuid, setgid, and sticky bits in file permissions (i.e., --S------
, -----S---
, and --------T
, respectively (aka 04000
, 02000
, and 01000
)).
IRWXU
, IRUSR
, IWUSR
, IXUSR
The same as the corresponding "S_"
bit masks from C's <sys/stat.h>
header file. These bit masks correspond to the user/owner file permissions (i.e., rwx------
, r--------
, -w-------
, and --x------
, respectively (aka 0700
, 0400
, 0200
, and 0100
)).
IRWXG
, IRGRP
, IWGRP
, IXGRP
The same as the corresponding "S_"
bit masks from C's <sys/stat.h>
header file. These bit masks correspond to the group file permissions (i.e., ---rwx---
, ---r-----
, ----w----
, and -----x---
, respectively (aka 0070
, 0040
, 0020
, and 0010
)).
IRWXO
, IROTH
, IWOTH
, IXOTH
The same as the corresponding "S_"
bit masks from C's <sys/stat.h>
header file. These bit masks correspond to the other/world file permissions (i.e., ------rwx
, ------r--
, -------w-
, and --------x
, respectively (aka 0007
, 0004
, 0002
, and 0001
)).
texists
This is true (i.e., non-zero) when the current candidate file is a symlink whose ultimate target exists (i.e., when rh(1) can obtain its stat(2) structure information). Note that a false value (i.e., zero) might be due to permissions, rather than non-existence.
It should be used with the ?:
or ||
or &&
operator (see above) to conditionally use any of the following stat(2) structure fields relating to symlink targets. Unless the target exists, their values are all zero and meaningless.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
Note: Even without the -y
or -Y
option (so symlinks are not followed for the purpose of searching), symlinks are followed for the purpose of obtaining the stat(2) structure information of the current candidate symlink's ultimate target so as to support the following target-related built-in symbols.
tdev
The device number of the device/filesystem that the current candidate symlink's ultimate target resides on. This is the st_dev
field of the corresponding stat(2) structure. See the related tmajor
and tminor
built-ins (next) for extracting the major and minor device numbers from tdev
.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tmajor
The major device number of the device/filesystem that the current candidate symlink's ultimate target resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tminor
The minor device number of the device/filesystem that the current candidate symlink's ultimate target resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tino
The inode number of the current candidate symlink's ultimate target. This is the st_ino
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tmode
The mode of the current candidate symlink's ultimate target. This is the st_mode
field of the corresponding stat(2) structure. This contains the file type and permissions. The standard library provides the ttype
and tperm
functions (among others) for extracting the file type and permissions from tmode
.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tnlink
The number of hard links to the current candidate symlink's ultimate target. This is the st_nlink
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tuid
The user ID of the owner of the current candidate symlink's ultimate target. This is the st_uid
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tgid
The group ID of the group of the current candidate symlink's ultimate target. This is the st_gid
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
trdev
The device number of the current candidate symlink's ultimate target. This is the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices. See the related trmajor
and trminor
built-ins (next) for extracting the major and minor device numbers from trdev
.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
trmajor
The major device number of the current candidate symlink's ultimate target. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
trminor
The minor device number of the current candidate symlink's ultimate target. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tsize
The size in bytes of the current candidate symlink's ultimate target file. This is the st_size
field of the corresponding stat(2) structure.
For an ultimate target that is a readable directory, this is not the st_size
field of the corresponding stat(2) structure. Instead, this is the number of entries it contains (excluding .
and ..
).
For an ultimate target that is an unreadable directory (and everything else), this is the usual (undocumented) st_size
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tblksize
The preferred block size for efficient I/O on the current candidate symlink's ultimate target's filesystem. This is the st_blksize
field of the corresponding stat(2) structure. On some filesystems (e.g., zfs), this is specific to each file, rather than to the whole filesystem.
Note that this is unrelated to the tblocks
built-in (see next).
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tblocks
The number of 512-byte blocks occupied by the current candidate symlink's ultimate target. This is the st_blocks
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tatime
The time that the current candidate symlink's ultimate target was last accessed. This is the st_atime
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tmtime
The time that the current candidate symlink's ultimate target's contents were last modified. This is the st_mtime
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tctime
The time that the current candidate symlink's ultimate target's inode was last changed. This is the st_ctime
field of the corresponding stat(2) structure.
This should only be used when the current candidate file is a symlink, and when its ultimate target exists (i.e., when texists
is true). Otherwise, this is zero.
Note: The -Y
option is incompatible with this built-in. The only symlinks seen will be broken ones, and this built-in will return zero.
tstrlen
This is the length in bytes of the base name of the current candidate symlink's immediate target path. Note that this is zero if the target path is the root directory (/
) which has no base name.
This should only be used when the current candidate file is a symlink. Otherwise, this is zero. But the ultimate target does not need to exist.
Note: The -Y
option affects this built-in. The only symlinks seen will be broken ones, but this built-in will still return the correct length.
By default, string literals ("
pattern"
) contain shell-style file glob patterns that are matched against each candidate file's base name. See the Pattern modifiers section below for variations.
Pattern strings evaluate to true (i.e., non-zero) if the pattern match succeeds, or false (i.e., zero) otherwise.
The following POSIX glob pattern notation is supported on all platforms:
?
Matches any single character. A leading dot character ("."
) is not treated as a special character. For example, ?profile
would match .profile
. This is unlike /bin/sh
behaviour, but it is like POSIX find(1) behaviour.
*
Matches any string of characters, including the empty string. A leading dot character ("."
) is not treated as a special character. For example, *
would match .profile
. This is unlike /bin/sh
behaviour, but it is like POSIX find(1) behaviour.
[abc]
Matches any single character in the given set. Ranges of characters can be specified (e.g., [a-z0-9]
).
[!abc]
Matches any single character that is not in the given set. Ranges of characters can be specified (e.g., [!A-Z]
).
And although it's non-standard (i.e., officially undefined), on most systems you can use the more familiar ^
instead of !
to complement the set in character classes (e.g., [^abc]
), but not on Solaris.
Locale-specific character class notation should also be available on all platforms (i.e., named character classes like [[:lower:]]
, collating symbols like [[.a-acute.]]
, and equivalence class expressions like [[=a=]]
), but not all locales support them all.
The special meanings of ?
, *
and [
can be removed by quoting them with a preceding backslash character ("\"
).
The following Ksh extended glob pattern notation is supported on platforms with GNU glibc (i.e., Linux):
?(a|b|c)
Matches if zero or one occurrences of any of the sub-patterns match the text.
*(a|b|c)
Matches if zero or more occurrences of any of the sub-patterns match the text.
+(a|b|c)
Matches if one or more occurrences of any of the sub-patterns match the text.
@(a|b|c)
Matches if exactly one occurrence of any of the sub-patterns matches the text.
!(a|b|c)
Matches if the text cannot be matched by any of the sub-patterns.
The special meanings of ?
, *
, +
, @
, !
, (
, |
and )
can be removed by quoting them with a preceding backslash character ("\"
).
The output of rh --help
states if Ksh extended glob pattern notation is available on the local system.
See fnmatch(3) and glob(7) for more details.
Pattern modifiers ("
pattern".
modifier) are suffixes to string literals that change how the string is interpreted, and what is done with it. There must be no spaces around the dot between the string literal and the modifier name.
Pattern modifier names can be supplied in full (e.g., "
pattern".path
), but a unique prefix is sufficient (e.g., "
pattern".pat
, "
pattern".pa
, or "
pattern".p
). For each of the pattern modifiers below, both the full name and the shortest unique prefix are shown.
The following modifiers exist, but not all are available on all systems.
path
(or p
)Apply the glob pattern to each candidate file's full path starting from the search directory, not just its base name. Slash characters ("/"
) are not treated as special characters. For example, "./sr*sc".path
would match ./src/misc
.
Note: Since a slash character can never appear in a file's base name, if a glob pattern string with no pattern modifier does contain a slash character (e.g., "/"
), then instead of attempting (and failing) to match it against the file's base name, an implicit path
pattern modifier is assumed (e.g., "/".path
), and it will be matched against the file's full path starting from the search directory instead.
link
(or l
)Apply the glob pattern to each candidate symlink's target path, rather than its base name. Slash characters ("/"
) are not treated as special characters. For example, "./sr*sc".path
would match ./src/misc
.
body
(or b
)Apply the glob pattern to each candidate file's contents, rather than its base name. Slash characters ("/"
) are not treated as special characters.
Note that this is an expensive pattern modifier because each candidate file is read in its entirety to determine whether or not the pattern matches. It can be worthwhile preceding this with other predicates to reduce the number and limit the size of candidate files that this is applied to.
This probably shouldn't be used with very large files. It would require a lot of memory or swap, and on 32-bit systems, the possible file size is also limited by the available address space. If this is an issue, you can always use grep(1) (or similar) via the sh
"pattern" modifier instead.
Also note that this only works with regular files that are readable to the current user.
Also note that the body
and ibody glob pattern modifiers shouldn't be used with binary files that might contain null bytes. For binary files, use the rebody
or reibody
regular expression pattern modifiers instead (see below).
Note: If the current candidate file is a symlink, its body is unaffected by the -y
or -Y
options. For the purpose of this predicate, the symlink is always followed.
what
(or w
)Apply the glob pattern to each candidate file's file type description (as would be output by the file(1) utility), rather than its base name. Slash characters ("/"
) are not treated as special characters. This is available on systems with libmagic(3) installed.
Note that this is an expensive pattern modifier because each candidate file is at least partially read to determine its file type. It can be worthwhile preceding this with other predicates to reduce the number of candidate files that this is applied to.
Also note that this only works with files that are readable to the current user.
Also note that any errors encountered result in an error message taking the place of the file type description being matched. To see these error messages, you can use the -L
option with its %w
format conversion.
Note: If the current candidate file is a symlink, its file type description is affected by the -y
or -Y
options.
mime
(or m
)Apply the glob pattern to each candidate file's MIME type (including the character set), rather than its base name. Slash characters ("/"
) are not treated as special characters. This is available on systems with libmagic(3) installed.
Note that this is an expensive pattern modifier because each candidate file is at least partially read to determine its MIME type. It can be worthwhile preceding this with other predicates to reduce the number of candidate files that this is applied to.
Also note that this only works with files that are readable to the current user.
Also note that any errors encountered result in an error message taking the place of the MIME type being matched. To see these error messages, you can use the -L
option with its %W
format conversion.
Note: If the current candidate file is a symlink, its MIME type is affected by the -y
or -Y
options.
i
Apply the glob pattern without case-sensitivity. This is available on most systems, but maybe not all.
The output of rh --help
states if case-insensitive glob matching is available on the local system.
ipath
(or ip
)Like the path
modifier, but apply the glob pattern without case-sensitivity. This is available on most systems, but maybe not all.
Note: Since a slash character can never appear in a file's base name, if a glob pattern string with the i
pattern modifier does contain a slash character (e.g., "/".i
), then instead of attempting (and failing) to match it against the file's base name, an implicit ipath
pattern modifier is assumed (e.g., "/".ipath
), and it will be matched against the file's full path starting from the search directory instead.
ilink
(or il
)Like the link
modifier, but apply the glob pattern without case-sensitivity. This is available on most systems, but maybe not all.
ibody
(or ib
)Like the body
modifier, but apply the glob pattern without case-sensitivity.
iwhat
(or iw
)Like the what
modifier, but apply the glob pattern without case-sensitivity. This is available on most systems with libmagic(3) installed, but maybe not all.
imime
(or im
)Like the mime
modifier, but apply the glob pattern without case-sensitivity. This is available on most systems with libmagic(3) installed, but maybe not all.
re
Match each candidate file's base name against a Perl-compatible regular expression (regex) instead of a glob pattern. See perlre(1), pcre2pattern(3), and pcre2syntax(3) for details. This is available on systems that have libpcre2-8 installed.
The output of rh --help
states whether or not Perl-compatible regular expressions are available on the local system.
Regex patterns are not automatically anchored to the start and end, and so do not have to match the entire text.
The following PCRE2 options are always enabled:
PCRE2_DOTALL
The .
meta-character matches any character, including the newline character. This prevents surprises when files have newline characters in their names. This is like Perl's /s
modifier.
PCRE2_MULTILINE
The ^
meta-character matches after every internal newline character, not just at the start. The $
meta-character matches before every internal newline character, not just at the end. This is useful for access control list (ACL) and extended attribute (EA) searches (see below) where the text can occupy multiple lines. This is like Perl's /m
modifier.
PCRE2_EXTENDED
Ignore (outside character classes) most whitespace characters and everything from a hash character ("#"
) until the end of the line. Matching a whitespace or hash character requires quoting it with a preceding backslash character ("\"
). Complex regex patterns can be made more readable this way, and it enables comments in regex patterns. This is like Perl's /x
modifier.
PCRE2_EXTENDED_MORE
Ignore space and tab characters inside character classes. Matching a space or tab in a character class requires quoting it with a preceding backslash character ("\"
). Complex character classes can be made more readable this way. This is like Perl's /xx
modifier.
PCRE2_NO_AUTO_CAPTURE
Prevent parentheses from automatically capturing matching text (i.e., always treat (
...)
as (?:
...)
). There are no uses for captures in rh(1), and this should make matching ever so slightly smaller and faster, without the explicit ?:
. This is like Perl's /n
modifier.
Note that the regex pattern and the text being matched are generally assumed to be encoded as UTF-8. If you need to suppress this assumption, set the environment variable RAWHIDE_PCRE2_NOT_UTF8_DEFAULT=1
. When this environment variable is set, individual regex patterns can still enable UTF-8 interpretation with a leading (*UTF)
. This UTF-8 assumption is made when the locale uses UTF-8 (i.e., when the $LANG
environment variable includes "UTF-8"
). When the locale doesn't use UTF-8, and you want rh to assume that everything is UTF-8 anyway, set the environment variable RAWHIDE_PCRE2_UTF8_DEFAULT=1
.
repath
(or rep
)Like the re
modifier, but apply the regex to each candidate file's full path starting from the search directory, not just its base name.
Note: Since a slash character can never appear in a file's base name, if a regex pattern string with the re
pattern modifier does contain a slash character (e.g., "/".re
), then instead of attempting (and failing) to match it against the file's base name, an implicit repath
pattern modifier is assumed (e.g., "/".repath
), and it will be matched against the file's full path starting from the search directory instead.
relink
(or rel
)Like the re
modifier, but apply the regex to each candidate symlink's target path, rather than its base name.
rebody
(or reb
)Like the re
modifier, but apply the regex to each candidate file's contents, rather than its base name. See body
above for more details.
rewhat
(or rew
)Like the re
modifier, but apply the regex to each candidate file's file type description, rather than its base name. This is available on systems that have libpcre2-8 and libmagic installed. See what
above for more details.
remime
(or rem
)Like the re
modifier, but apply the regex to each candidate file's MIME type, rather than its base name. This is available on systems that have libpcre2-8 and libmagic installed. See mime
above for more details.
rei
Like the re
modifier, but apply the regex without case-sensitivity.
reipath
(or reip
)Like the repath
modifier, but apply the regex without case-sensitivity.
Note: Since a slash character can never appear in a file's base name, if a regex pattern string with the rei
pattern modifier does contain a slash character (e.g., "/".rei
), then instead of attempting (and failing) to match it against the file's base name, an implicit reipath
pattern modifier is assumed (e.g., "/".reipath
), and it will be matched against the file's full path starting from the search directory instead.
reilink
(or reil
)Like the relink
modifier, but apply the regex without case-sensitivity.
reibody
(or reib
)Like the rebody
modifier, but apply the regex without case-sensitivity.
reiwhat
(or reiw
)Like the rewhat
modifier, but apply the regex without case-sensitivity.
reimime
(or reim
)Like the remime
modifier, but apply the regex without case-sensitivity.
acl
(or a
)Apply the glob pattern to each candidate file's access control list (ACL), rather than its base name.
This is available on systems with "POSIX" ACLs (e.g., Linux, FreeBSD, Solaris (for ufs), and Cygwin), and NFSv4 ACLs (e.g., FreeBSD and Solaris (for zfs)), and macOS with its own Extended ACLs. OpenBSD and NetBSD don't do ACLs. See acl(2) or acl(3) or acl(5) for more details.
The output of rh --help
states if access control lists are available on the local system.
"POSIX" ACL text consists of multiple lines, each terminated by a newline character. It looks like this:
user::rwx
user:name:rwx
group::rwx
group:name:rwx
mask::rwx
other::rwx
NFSv4 ACL text comes in two forms. In the compact form, the items look like these:
owner@:rwxp--aARWcCos:-------:allow
user:name:rwxp--aARWcCos:-------:allow
group@:r-x---a-R-c--s:-------:allow
group:name:r-x---a-R-c--s:-------:allow
everyone@:r-x---a-R-c--s:-------:allow
In the non-compact form, the items each look something like this:
owner@:read_data/write_data/append_data/read_xattr/write_xattr
/execute/read_attributes/write_attributes/read_acl/write_acl
/write_owner/synchronize:allow
Searches can be made for either form. But be warned that the permission names in the non-compact form do not always appear in the same order (at least on Solaris).
On FreeBSD, NFSv4 ACL text has each item on a separate line, terminated by a newline character, and there are leading spaces for vertical alignment before each item. On Solaris, NFSv4 ACL text is a comma-separated list of items with no leading spaces and no newline character.
macOS has its own Extended ACLs that look like this:
!#acl 1
user:906E2CAD-E971-12D8-ACB9-000A95DF094B:drew:502:allow:write
An easy way to see what ACLs look like on your system is:
$ rh -L '%p\n%z\n'
But bear in mind that this reformats multiple lines into a comma-separated list. That can be avoided if the locale uses UTF-8 and jq(1) is installed:
$ rh -L %j | jq -r .access_control_list
Note that glob patterns are anchored to the start and end, and so must match the entire text.
On Solaris, ACLs are always present by default, even if they are trivially identical to the file permission bits. This can be convenient, but if it seems like noise, it can be silenced (but only on Solaris) by setting the environment variable RAWHIDE_SOLARIS_ACL_NO_TRIVIAL=1
.
iacl
(or ia
)Like the acl
modifier, but apply the glob pattern without case-sensitivity. This might not be available on all systems.
reacl
(or rea
)Like the acl
modifier, but match each candidate file's access control list (ACL) against a Perl-compatible regular expression (regex) instead of a glob pattern. This is available on systems that have libpcre2-8 installed, and supported access control lists. See the re
modifier above for more information.
reiacl
(or reia
)Like the reacl
modifier, but apply the regex without case-sensitivity.
ea
(or e
)Apply the glob pattern to each candidate file's extended attributes (EA), rather than its base name.
This is available on Linux, FreeBSD, macOS, Solaris, and Cygwin. OpenBSD and NetBSD don't do EAs. See xattr(1) or xattr(7) or extattr(2) or fsattr(7) for more details.
The output of rh --help
states if extended attributes are available on the local system.
The extended attributes text, if any, will be possibly multiple lines, one per extended attribute, each terminated by a newline character. Each extended attribute starts with its name. If it also has a value, then the name is followed by colon and space characters (": "
), and then the value. Note that on macOS, some extended attribute names contain a colon character, but they aren't typically followed by a space character.
Note that any control characters (i.e., ASCII 0-31, 127) in extended attribute names or values, and any non-ASCII bytes (i.e., 128-255) in the values, will be presented as C-like backslash escape sequences such as "\n"
for the newline character, and "\0"
for the null character, or as hexadecimal escape sequences such as "\x1b"
for the escape character. Any backslash characters are quoted with a preceding backslash. Note that commas are not quoted.
This encoding is the text that patterns must be written to match against. But you can still match against any text in extended attribute names, and ASCII-only text in their values, as you normally would.
Note that glob patterns are anchored to the start and end, and so must match the entire text.
On FreeBSD, extended attributes in the user namespace are presented with "user."
as a prefix to their actual name, and those in the system namespace are presented with "system."
as a name prefix. On FreeBSD, only the root
user may see extended attributes in the system namespace.
On most systems with extended attributes, the values are typically only up to a few hundred bytes in size. But on Solaris, extended attributes take the form of regular files in a special extended attributes directory "hidden" inside each real file. Entire files can be copied into that special directory, and they become extended attributes. So extended attributes could tend to be larger on Solaris.
The default maximum total size for (encoded) extended attributes is 4KiB on most systems, and 64KiB on Solaris. If this is not enough, extended attributes will be silently truncated. This affects extended attribute searching (ea
), and the -L %x
format conversion. To prevent truncation, set the environment variable RAWHIDE_EA_SIZE
to a positive integer value that is large enough for your needs. Note that the value must be the size in bytes. Scale units are not supported.
On Solaris, every file's extended attributes directory contains the SUNWattr_ro and SUNWattr_rw extended attributes. By default, they are included for every file that has any other extended attributes. They can be excluded by setting the environment variable RAWHIDE_SOLARIS_EA_NO_SUNWATTR=1
.
Also on Solaris, since extended attributes are files (of a sort), they each have their own stat(2) information. By default, this information is represented as an artificial extended attribute whose name is the name of the corresponding real extended attribute followed by "/stat"
. These artificial extended attributes have the following format:
name/stat: -rw-r--r-- nlink user group size mtime atime ctime
The name is the name of the corresponding real extended attribute. The "/stat:"
is literal. The nlink is always 1
. The user and group are names or numeric IDs. The size is in bytes. The mtime, atime, and ctime are in ISO date/time format ("YYYY-MM-DD HH:MM:SS +HHMM"
).
This makes it possible on Solaris to search for files by the stat(2) information of their extended attributes. But it can only be a text-based search (glob or regex).
These artificial extended attributes can be suppressed by setting the environment variable RAWHIDE_SOLARIS_EA_NO_STATINFO=1
.
iea
(or ie
)Like the ea
modifier, but apply the glob pattern without case-sensitivity. This might not be available on all systems.
reea
(or ree
)Like the ea
modifier, but match each candidate file's extended attributes (EA) against a Perl-compatible regular expression (regex) instead of a glob pattern. This is available on systems that have libpcre2-8 installed, and supported extended attributes. See the re
modifier above for more information.
reiea
(or reie
)Like the reea
modifier, but apply the regex without case-sensitivity.
sh
(or s
)This interprets the string literal, not as a pattern at all, but as an external shell command to execute via system(3) (i.e., via /bin/sh
). It evaluates to the exit success status of the external shell command. If its exit status is zero, then the value is true (i.e., non-zero). Otherwise, it is false (i.e., zero).
This enables arbitrary command line utilities to contribute to the search criteria. But be warned, this can be slow, because it involves the creation of possibly many other processes. But it makes many things possible. To reduce the number of external shell commands that need to be executed, the sh
"pattern" modifier can be used conditionally with the ?:
or ||
or &&
operator (see above).
The string can contain %s
which will be replaced with the matching entry's full path starting from the search directory. It can also contain %S
which will be replaced with the matching entry's base name (or with "/"
when the matching entry is the root directory (/
) which has no base name). For example, given the matching file /etc/passwd
, %s
and %S
would be replaced with "/etc/passwd"
and "passwd"
, respectively. To include a literal per cent sign ("%"
) in the shell command, use %%
. It is an error if %
is not followed by s
, S
, or %
.
Any shell meta-characters in the interpolated path or base name are quoted with preceding backslash characters ("\"
) to prevent shell command injection, so there is no need to place any quote characters around %s
or %S
.
Every shell command is executed after safely changing the current working directory to the directory containing each candidate file. This minimizes the number of path-based race conditions. So the %S
interpolation is more likely to be useful than the %s
interpolation.
And if the user's $PATH
environment variable includes the current working directory, or any other non-absolute paths, that could be dangerous, so they are automatically removed first.
Note: Since the shell commands are executed from the directory containing each matching entry, if they do require the matching entry's full path starting from the search directory (i.e., %s
), then it's best if the starting search paths are all absolute paths, so that %s
is always an absolute path. Otherwise, the shell command might need to change its current working directory back to the initial working directory. Also note that %s
suffers from many path-based race conditions, which is insecure on hosts with malicious local actors that have write access to the directory tree being searched, and so should not generally be used.
Reference file fields ("
/path".
field) are suffixes to string literals that represent the inode metadata of arbitrary reference files for the purpose of comparison. There must be no spaces around the dot between the path string and the field name.
If the path is the empty string (e.g., "".
field), then it refers to the most recent reference file path encountered by the parser. This makes multiple references to the same reference file more concise (e.g., "/path".exists && mtime > "".mtime
).
The following reference file fields are available.
exists
This is true (i.e., non-zero) when the reference file exists (i.e., when rh(1) can obtain its stat(2) structure information). Note that a false value (i.e., zero) might be due to permissions, rather than non-existence.
If there is any chance that a reference file does not exist, then the exists
field must be used to determine whether or not most of the other reference file fields can be used. If a reference file does not exist, and any of its stat(2) structure fields below are used in a file test expression, an error message will be output, and rh(1) will terminate with a non-zero exit status. exists
is to be used with the ?:
or ||
or &&
operator (see above) to conditionally use any of the following stat(2) structure fields (e.g., "/path".exists && size > "".size
).
dev
The device number of the device/filesystem that the reference file resides on. This is the st_dev
field of the corresponding stat(2) structure. See the related major
and minor
reference file fields (next) for extracting the major and minor device numbers from dev
.
It is an error to use this if the reference file does not exist. See exists
above.
major
The major device number of the device/filesystem that the reference file resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
minor
The minor device number of the device/filesystem that the reference file resides on. This is part of the st_dev
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
ino
The inode number of the reference file. This is the st_ino
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
mode
The mode of the reference file. This is the st_mode
field of the corresponding stat(2) structure. This contains the file type and permissions. See the related type
and perm
reference file fields (next) for extracting the file type and permissions from mode
.
It is an error to use this if the reference file does not exist. See exists
above.
type
The file type of the reference file (i.e., an alias for mode & IFMT
).
It is an error to use this if the reference file does not exist. See exists
above.
perm
The file permissions of the reference file (i.e., an alias for mode & ~IFMT
).
It is an error to use this if the reference file does not exist. See exists
above.
nlink
The number of hard links to the reference file. This is the st_nlink
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
uid
The user ID of the owner of the reference file. This is the st_uid
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
gid
The group ID of the group of the reference file. This is the st_gid
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
rdev
The device number of the reference file. This is the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices. See the related rmajor
and rminor
reference file fields (next) for extracting the major and minor device numbers from rdev
.
It is an error to use this if the reference file does not exist. See exists
above.
rmajor
The major device number of the reference file. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
It is an error to use this if the reference file does not exist. See exists
above.
rminor
The minor device number of the reference file. This is part of the st_rdev
field of the corresponding stat(2) structure. This is only meaningful for character devices and block devices.
It is an error to use this if the reference file does not exist. See exists
above.
size
The size in bytes of the reference file. This is the st_size
field of the corresponding stat(2) structure.
For reference files that are symlinks (that are not followed with the -y
or -Y
option), this is the length in bytes of the target path.
For reference files that are readable directories, this is not the st_size
field of the corresponding stat(2) structure. Instead, this is the number of entries it contains (excluding .
and ..
).
For reference files that are unreadable directories (and everything else), this is the usual (undocumented) st_size
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
blksize
The preferred block size for efficient I/O on the reference file's filesystem. This is the st_blksize
field of the corresponding stat(2) structure. On some filesystems (e.g., zfs), this is specific to each file, rather than to the whole filesystem.
Note that this is unrelated to the blocks
reference file field (see next).
It is an error to use this if the reference file does not exist. See exists
above.
blocks
The number of 512-byte blocks occupied by the reference file. This is the st_blocks
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
atime
The time that the reference file was last accessed. This is the st_atime
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
mtime
The time that the reference file's contents were last modified. This is the st_mtime
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
ctime
The time that the reference file's inode was last changed. This is the st_ctime
field of the corresponding stat(2) structure.
It is an error to use this if the reference file does not exist. See exists
above.
attr
On Linux, the reference file's ext2-style file attribute bit mask. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details. See /etc/rawhide.conf.d/attributes
for all the related constants (e.g., ATTR_IMMUTABLE
, ATTR_APPEND
, ...).
It is an error to use this if the reference file does not exist. See exists
above.
Note: If the reference file is a symlink, it is never followed for the purpose of obtaining the file attributes. This is a decision made by libe2p. This is not affected by the -y
or -Y
options. Also note that symlinks do not have their own file attributes (i.e., attr
is zero).
On Linux, this is only available on systems with libe2p. On Linux systems without libe2p, this is not a built-in symbol. Instead, this is a place-holder function that returns zero.
This is also available on FreeBSD, OpenBSD, NetBSD, and macOS. The attributes/flags that are available vary from system to system. See chflags(1) for details. See /etc/rawhide.conf.d/attributes
for all the related predicate functions (e.g., uimmutable
, uappend
, nodump
, opaque
, ...).
On other systems, this doesn't exist at all.
proj
On Linux, the reference file's ext2-style file project number. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details.
It is an error to use this if the reference file does not exist. See exists
above.
Note: If the reference file is a symlink, it is always followed for the purpose of obtaining the file project. This is not affected by the -y
or -Y
options.
Note: This is only available on Linux systems with libe2p. On other systems, this doesn't exist at all.
gen
On Linux, the reference file's ext2-style version/generation number. Not all file systems support all file attributes. See chattr(1) and lsattr(1) for details.
It is an error to use this if the reference file does not exist. See exists
above.
Note: If the reference file is a symlink, it is always followed for the purpose of obtaining the file version/generation. This is not affected by the -y
or -Y
options.
Note: This is only available on Linux systems with libe2p. On other systems, this doesn't exist at all.
strlen
The length in bytes of the base name of the reference file. Note that this is zero if the reference file is the root directory (/
) which has no base name.
inode
An alias for ino
.
It is an error to use this if the reference file does not exist. See exists
above.
nlinks
An alias for nlink
.
It is an error to use this if the reference file does not exist. See exists
above.
user
An alias for uid
.
It is an error to use this if the reference file does not exist. See exists
above.
group
An alias for gid
.
It is an error to use this if the reference file does not exist. See exists
above.
sz
An alias for size
.
It is an error to use this if the reference file does not exist. See exists
above.
accessed
An alias for atime
.
It is an error to use this if the reference file does not exist. See exists
above.
modified
An alias for mtime
.
It is an error to use this if the reference file does not exist. See exists
above.
changed
An alias for ctime
.
It is an error to use this if the reference file does not exist. See exists
above.
len
An alias for strlen
.
This is the default /etc/rawhide.conf
standard library:
# /etc/rawhide.conf: rh system-wide configuration.
# See rh(1) and rawhide.conf(5) for more information.
/*
This file constitutes the rawhide standard library.
On some systems, this file could be somewhere other than /etc
(e.g., /usr/local/etc, /opt/local/etc, /usr/pkg/etc).
You can modify this file, and/or place additional files
in the /etc/rawhide.conf.d directory.
They'll be read after this file, in lexicographic order.
Any files whose names start with dot are skipped.
You can also create your own user-specific rawhide
functions in ~/.rhrc and ~/.rhrc.d/*. They'll be read
by rh in the same manner after these system-wide files.
*/
// File types (canonical, aliases)
type { mode & IFMT }
reg { type == IFREG }
dir { type == IFDIR }
blk { type == IFBLK }
chr { type == IFCHR }
lnk { type == IFLNK }
sock { type == IFSOCK }
fifo { type == IFIFO }
door { type == IFDOOR } # Solaris
file { reg }
directory { dir }
block { blk }
char { chr }
device { blk || chr }
symlink { lnk }
link { lnk }
socket { sock }
namedpipe { fifo }
pipe { fifo }
f { reg }
d { dir }
b { blk }
c { chr }
l { lnk }
s { sock }
p { fifo }
D { door } # Solaris
// File permissions (canonical, aliases, helpers)
perm { mode & ~IFMT }
ur { perm & IRUSR }
uw { perm & IWUSR }
ux { perm & IXUSR }
gr { perm & IRGRP }
gw { perm & IWGRP }
gx { perm & IXGRP }
or { perm & IROTH }
ow { perm & IWOTH }
ox { perm & IXOTH }
wr { perm & IROTH }
ww { perm & IWOTH }
wx { perm & IXOTH }
user_readable { ur }
user_writable { uw }
user_executable { ux }
group_readable { gr }
group_writable { gw }
group_executable { gx }
other_readable { or }
other_writable { ow }
other_executable { ox }
world_readable { wr }
world_writable { ww }
world_executable { wx }
suid { perm & ISUID }
sgid { perm & ISGID }
svtx { perm & ISVTX }
setuid { suid }
setgid { sgid }
sticky { svtx }
all(bitmask) { (perm & bitmask) == bitmask }
any(bitmask) { perm & bitmask }
none(bitmask) { !any(bitmask) }
allr { all(IRUSR | IRGRP | IROTH) }
allw { all(IWUSR | IWGRP | IWOTH) }
allx { all(IXUSR | IXGRP | IXOTH) }
anyr { any(IRUSR | IRGRP | IROTH) }
anyw { any(IWUSR | IWGRP | IWOTH) }
anyx { any(IXUSR | IXGRP | IXOTH) }
noner { !anyr }
nonew { !anyw }
nonex { !anyx }
all_readable { allr }
all_writable { allw }
all_executable { allx }
any_readable { anyr }
any_writable { anyw }
any_executable { anyx }
none_readable { noner }
none_writable { nonew }
none_executable { nonex }
// Aliases for built-ins
inode { ino }
nlinks { nlink }
user { uid }
group { gid }
space { blocks * 512 }
accessed { atime }
modified { mtime } # Refers to the contents
changed { ctime } # Refers to the inode
len { strlen }
sz { size }
seconds { second }
minutes { minute }
hours { hour }
days { day }
weeks { week }
months { month }
years { year }
quit { exit }
imayread { readable } # Uses access(2) not perm
imaywrite { writable } # Uses access(2) not perm
imayexec { executable } # Uses access(2) not perm
ir { readable }
iw { writable }
ix { executable }
// File types for symlink targets (canonical, aliases)
ttype { tmode & IFMT }
treg { ttype == IFREG }
tdir { ttype == IFDIR }
tblk { ttype == IFBLK }
tchr { ttype == IFCHR }
tsock { ttype == IFSOCK }
tfifo { ttype == IFIFO }
tdoor { ttype == IFDOOR } # Solaris
tfile { treg }
tdirectory { tdir }
tblock { tblk }
tchar { tchr }
tdevice { tblk || tchr }
tsocket { tsock }
tnamedpipe { tfifo }
tpipe { tfifo }
tf { treg }
td { tdir }
tb { tblk }
tc { tchr }
ts { tsock }
tp { tfifo }
tD { tdoor } # Solaris
target_type { ttype }
target_reg { treg }
target_dir { tdir }
target_blk { tblk }
target_chr { tchr }
target_sock { tsock }
target_fifo { tfifo }
target_door { tdoor } # Solaris
target_file { treg }
target_directory { tdir }
target_block { tblk }
target_char { tchr }
target_device { tblk || tchr }
target_socket { tsock }
target_namedpipe { tfifo }
target_pipe { tfifo }
target_f { treg }
target_d { tdir }
target_b { tblk }
target_c { tchr }
target_s { tsock }
target_p { tfifo }
target_D { tdoor }
// File permissions for symlink targets (canonical, aliases, helpers)
tperm { tmode & ~IFMT }
tur { tperm & IRUSR }
tuw { tperm & IWUSR }
tux { tperm & IXUSR }
tgr { tperm & IRGRP }
tgw { tperm & IWGRP }
tgx { tperm & IXGRP }
tor { tperm & IROTH }
tow { tperm & IWOTH }
tox { tperm & IXOTH }
twr { tperm & IROTH }
tww { tperm & IWOTH }
twx { tperm & IXOTH }
target_perm { tperm }
target_ur { tur }
target_uw { tuw }
target_ux { tux }
target_gr { tgr }
target_gw { tgw }
target_gx { tgx }
target_or { tor }
target_ow { tow }
target_ox { tox }
target_wr { twr }
target_ww { tww }
target_wx { twx }
target_user_readable { tur }
target_user_writable { tuw }
target_user_executable { tux }
target_group_readable { tgr }
target_group_writable { tgw }
target_group_executable { tgx }
target_other_readable { tor }
target_other_writable { tow }
target_other_executable { tox }
target_world_readable { twr }
target_world_writable { tww }
target_world_executable { twx }
tsuid { tperm & ISUID }
tsgid { tperm & ISGID }
tsvtx { tperm & ISVTX }
tsetuid { tsuid }
tsetgid { tsgid }
tsticky { tsvtx }
target_suid { tsuid }
target_sgid { tsgid }
target_svtx { tsvtx }
target_setuid { tsuid }
target_setgid { tsgid }
target_sticky { tsvtx }
tall(bitmask) { (tperm & bitmask) == bitmask }
tany(bitmask) { tperm & bitmask }
tnone(bitmask) { !tany(bitmask) }
tallr { tall(IRUSR | IRGRP | IROTH) }
tallw { tall(IWUSR | IWGRP | IWOTH) }
tallx { tall(IXUSR | IXGRP | IXOTH) }
tanyr { tany(IRUSR | IRGRP | IROTH) }
tanyw { tany(IWUSR | IWGRP | IWOTH) }
tanyx { tany(IXUSR | IXGRP | IXOTH) }
tnoner { !tanyr }
tnonew { !tanyw }
tnonex { !tanyx }
target_all(bitmask) { tall(bitmask) }
target_any(bitmask) { tany(bitmask) }
target_none(bitmask) { tnone(bitmask) }
target_allr { tallr }
target_allw { tallw }
target_allx { tallx }
target_anyr { tanyr }
target_anyw { tanyw }
target_anyx { tanyx }
target_noner { tnoner }
target_nonew { tnonew }
target_nonex { tnonex }
target_all_readable { tallr }
target_all_writable { tallw }
target_all_executable { tallx }
target_any_readable { tanyr }
target_any_writable { tanyw }
target_any_executable { tanyx }
target_none_readable { tnoner }
target_none_writable { tnonew }
target_none_executable { tnonex }
// Aliases for symlink target built-ins
target_exists { texists }
target_dev { tdev }
target_ino { tino }
target_mode { tmode }
target_nlink { tnlink }
target_uid { tuid }
target_gid { tgid }
target_rdev { trdev }
target_size { tsize }
target_blksize { tblksize }
target_blocks { tblocks }
target_atime { tatime }
target_mtime { tmtime }
target_ctime { tctime }
target_strlen { tstrlen }
tinode { tino }
tnlinks { tnlink }
tuser { tuid }
tgroup { tgid }
tspace { tblocks * 512 }
taccessed { tatime }
tmodified { tmtime } # Refers to the target's contents
tchanged { tctime } # Refers to the target's inode
tlen { tstrlen }
tsz { tsize }
target_inode { tinode }
target_nlinks { tnlinks }
target_user { tuser }
target_group { tgroup }
target_space { tspace }
target_accessed { taccessed }
target_modified { tmodified }
target_changed { tchanged }
target_len { tlen }
target_sz { tsz }
// Aliases for size units
KiB { 1K }
MiB { 1M }
GiB { 1G }
TiB { 1T }
PiB { 1P }
EiB { 1E }
KB { 1k }
MB { 1m }
GB { 1g }
TB { 1t }
PB { 1p }
EB { 1e }
// Miscellaneous helper functions
empty { size == 0 } # Only for files and readable directories
roots { uid == 0 }
mine { uid == $$ }
ours { gid == @@ }
broken { symlink && !texists }
dangling { broken }
gmtoday { now - now % day }
ago(sec) { now - sec }
old(sec) { mtime <= ago(sec) }
past(sec) { mtime >= ago(sec) }
min(x, y) { (x < y) ? x : y }
max(x, y) { (x > y) ? x : y }
abs(x) { (x < 0) ? -x : x }
// Examples
// Complex tests can be very readable (and/or very concise)
// rootshell { setuid && roots && (group_writable | other_writable) }
// rootshell { suid && roots && (gw | ow) }
// csrc { "*.[ch]" || "[Mm]akefile" }
// oldaout { "a.out" && f && old(week) }
// oldcore { "^core(\.\d+)?$".re && f && old(week) }
// bad { oldaout || oldcore || "*.BAK" || "*.CKP" || (gw | ow) }
// Note: Read "<" and ">" as before/after, not as less/more than
// recent { modified >= ago(hour) }
// Silly recursive functions are possible (but not mutual recursion)
// sqrt1(n, odd) { (n <= 0) ? 0 : sqrt1(n - odd, odd + 2) + 1 }
// sqrt(n) { sqrt1(n, 1) }
// prime1(n, i) { (i * i > n) ? 1 : !(n % i) ? 0 : prime1(n, i + 2) }
// prime(n) { (n < 2) ? 0 : !(n % 2) ? n == 2 : prime1(n, 3) }
// factorial(x) { (x > 0) ? x * factorial(x - 1) : 1 }
// ack(x, y) { !x ? y+1 : !y ? ack(x-1, 1) : ack(x-1, ack(x, y-1)) }
The following aliases provide greater brevity for some built-ins. Perhaps they could have gone into the standard library, but you might have better uses for these identifiers.
// Brevity (aliases)
i { ino }
n { nlink }
u { uid }
g { gid }
a { atime }
m { mtime }
su { suid }
sg { sgid }
nu { nouser }
ng { nogroup }
r { readable }
w { writable }
x { executable }
q { exit }
sec { second }
mn { minute }
hr { hour }
dy { day }
wk { week }
mth { month }
yr { year }
On Linux systems with libe2p, this is the /etc/rawhide.conf.d/attributes
library:
# /etc/rawhide.conf.d/attributes (Linux)
# See rh(1) and rawhide.conf(5) for more information.
/*
This file defines aliases for the built-in symbols for the
Linux ext2-style file attributes, and the related constants
and predicates. See <e2p/e2p.h> and <ext2fs/ext2_fs.h>.
*/
// Aliases for the Linux ext2-style attribute built-ins
flag { attr }
flags { attr }
attrs { attr }
attribute { attr }
attributes { attr }
project { proj }
generation { gen }
// Attribute constants from <ext2fs/ext2_fs.h>
ATTR_SECRM { 0x00000001 } # Secure deletion
ATTR_UNRM { 0x00000002 } # Undelete
ATTR_COMPR { 0x00000004 } # Compress file
ATTR_SYNC { 0x00000008 } # Synchronous updates
ATTR_IMMUTABLE { 0x00000010 } # Immutable file
ATTR_APPEND { 0x00000020 } # Writes to file may only append
ATTR_NODUMP { 0x00000040 } # Do not dump file
ATTR_NOATIME { 0x00000080 } # Do not update atime
ATTR_DIRTY { 0x00000100 }
ATTR_COMPRBLK { 0x00000200 } # One or more compressed clusters
ATTR_NOCOMPR { 0x00000400 } # Access raw compressed data
ATTR_ENCRYPT { 0x00000800 } # Encrypted
ATTR_BTREE { 0x00001000 } # Btree format directory
ATTR_INDEX { 0x00001000 } # Hash-indexed directory
ATTR_IMAGIC { 0x00002000 }
ATTR_JOURNAL_DATA { 0x00004000 } # File data should be journaled
ATTR_NOTAIL { 0x00008000 } # File tail should not be merged
ATTR_DIRSYNC { 0x00010000 } # Synchronous dir modifications
ATTR_TOPDIR { 0x00020000 } # Top of directory hierarchies
ATTR_HUGE_FILE { 0x00040000 } # Set to each huge file
ATTR_EXTENTS { 0x00080000 } # Inode uses extents
ATTR_VERITY { 0x00100000 } # Verity protected inode
ATTR_EA_INODE { 0x00200000 } # Inode used for large EA
ATTR_NOCOW { 0x00800000 } # Do not cow file
ATTR_SNAPFILE { 0x01000000 } # Inode is a snapshot
ATTR_DAX { 0x02000000 } # Inode is DAX
ATTR_SNAPFILE_DELETED { 0x04000000 } # Snapshot is being deleted
ATTR_SNAPFILE_SHRUNK { 0x08000000 } # Snapshot shrink has completed
ATTR_INLINE_DATA { 0x10000000 } # Inode has inline data
ATTR_PROJINHERIT { 0x20000000 } # Create with parents projid
ATTR_CASEFOLD { 0x40000000 } # Casefolded file
// Attribute predicates (canonical, aliases)
secrm { attr & ATTR_SECRM }
unrm { attr & ATTR_UNRM }
compr { attr & ATTR_COMPR }
sync { attr & ATTR_SYNC }
immutable { attr & ATTR_IMMUTABLE }
append { attr & ATTR_APPEND }
nodump { attr & ATTR_NODUMP }
noatime { attr & ATTR_NOATIME }
dirty { attr & ATTR_DIRTY }
comprblk { attr & ATTR_COMPRBLK }
nocompr { attr & ATTR_NOCOMPR }
encrypt { attr & ATTR_ENCRYPT }
btree { attr & ATTR_BTREE }
index { attr & ATTR_INDEX }
imagic { attr & ATTR_IMAGIC }
journal_data { attr & ATTR_JOURNAL_DATA }
notail { attr & ATTR_NOTAIL }
dirsync { attr & ATTR_DIRSYNC }
topdir { attr & ATTR_TOPDIR }
huge_file { attr & ATTR_HUGE_FILE }
extents { attr & ATTR_EXTENTS }
verity { attr & ATTR_VERITY }
ea_inode { attr & ATTR_EA_INODE }
nocow { attr & ATTR_NOCOW }
snapfile { attr & ATTR_SNAPFILE }
dax { attr & ATTR_DAX }
snapfile_deleted { attr & ATTR_SNAPFILE_DELETED }
snapfile_shrunk { attr & ATTR_SNAPFILE_SHRUNK }
inline_data { attr & ATTR_INLINE_DATA }
projinherit { attr & ATTR_PROJINHERIT }
casefold { attr & ATTR_CASEFOLD }
secure_deletion { secrm }
undelete { unrm }
compressed { compr }
synchronous { sync }
append_only { append }
nocompression { nocompr }
encrypted { encrypt }
indexed { index }
direct_access { dax }
inherit_project { projinherit }
attr_s { secrm }
attr_u { unrm }
attr_c { compr }
attr_S { sync }
attr_i { immutable }
attr_a { append }
attr_d { nodump }
attr_A { noatime }
attr_m { nocompr }
attr_E { encrypt }
attr_I { index }
attr_j { journal_data }
attr_t { notail }
attr_D { dirsync }
attr_T { topdir }
attr_e { extents }
attr_V { verity }
attr_C { nocow }
attr_x { dax }
attr_N { inline_data }
attr_P { projinherit }
attr_F { casefold }
On FreeBSD systems, this is the /etc/rawhide.conf.d/attributes
library. There is a similar file on OpenBSD, NetBSD, and macOS systems:
# /etc/rawhide.conf.d/attributes (FreeBSD)
# See rh(1) and rawhide.conf(5) for more information.
/*
This file defines aliases for the built-in symbols for FreeBSD file
flags, and the related constants and predicates. See <sys/stat.h>.
*/
// Aliases for the FreeBSD file flags built-ins
flag { attr }
flags { attr }
attrs { attr }
attribute { attr }
attributes { attr }
project { 0 }
generation { 0 }
// Flag constants from <sys/stat.h>
# Super-user and owner changeable flags
UF_SETTABLE { 0x0000ffff } # mask of owner changeable flags
UF_NODUMP { 0x00000001 } # do not dump file
UF_IMMUTABLE { 0x00000002 } # file may not be changed
UF_APPEND { 0x00000004 } # writes to file may only append
UF_OPAQUE { 0x00000008 } # directory is opaque wrt. union
UF_NOUNLINK { 0x00000010 } # file may not be removed or renamed
UF_SYSTEM { 0x00000080 } # Windows system file bit
UF_SPARSE { 0x00000100 } # sparse file
UF_OFFLINE { 0x00000200 } # file is offline
UF_REPARSE { 0x00000400 } # Windows reparse point file bit
UF_ARCHIVE { 0x00000800 } # file needs to be archived
UF_READONLY { 0x00001000 } # Windows readonly file bit
UF_HIDDEN { 0x00008000 } # file is hidden [same as macOS]
# Super-user changeable flags
SF_SETTABLE { 0xffff0000 } # mask of superuser changeable flags
SF_ARCHIVED { 0x00010000 } # file is archived
SF_IMMUTABLE { 0x00020000 } # file may not be changed
SF_APPEND { 0x00040000 } # writes to file may only append
SF_NOUNLINK { 0x00100000 } # file may not be removed or renamed
SF_SNAPSHOT { 0x00200000 } # snapshot inode
// Flag predicates (canonical, aliases)
arch { attr & SF_ARCHIVED }
archived { attr & SF_ARCHIVED }
nodump { attr & UF_NODUMP }
opaque { attr & UF_OPAQUE }
sappnd { attr & SF_APPEND }
sappend { attr & SF_APPEND }
schg { attr & UF_IMMUTABLE }
schange { attr & UF_IMMUTABLE }
simmutable { attr & UF_IMMUTABLE }
snapshot { attr & SF_SNAPSHOT }
sunlnk { attr & SF_NOUNLINK }
sunlink { attr & SF_NOUNLINK }
uappnd { attr & UF_APPEND }
uappend { attr & UF_APPEND }
uarch { attr & UF_ARCHIVE }
uarchive { attr & UF_ARCHIVE }
uchg { attr & SF_IMMUTABLE }
uchange { attr & SF_IMMUTABLE }
uimmutable { attr & SF_IMMUTABLE }
uhidden { attr & UF_HIDDEN }
hidden { attr & UF_HIDDEN }
uoffline { attr & UF_OFFLINE }
offline { attr & UF_OFFLINE }
urdonly { attr & UF_READONLY }
rdonly { attr & UF_READONLY }
readonly { attr & UF_READONLY }
usparse { attr & UF_SPARSE }
sparse { attr & UF_SPARSE }
usystem { attr & UF_SYSTEM }
system { attr & UF_SYSTEM }
ureparse { attr & UF_REPARSE }
reparse { attr & UF_REPARSE }
uunlnk { attr & UF_NOUNLINK }
uunlink { attr & UF_NOUNLINK }
append { uappend | sappend }
immutable { uimmutable | simmutable }
nounlink { uunlink | sunlink }
unlink { uunlink | sunlink }
See rh(1) for more examples.
The following source/configuration files are read by default:
/etc/rawhide.conf - main system-wide configuration
/etc/rawhide.conf.d/* - additional system-wide configuration
~/.rhrc - main user-specific configuration
~/.rhrc.d/* - additional user-specific configuration
The location of the system-wide configuration might be somewhere else, depending on the operating system preferences (e.g., /usr/local/etc
, /opt/local/etc
, /usr/pkg/etc
).
The output of rh --help
states where the system-wide configuration files are on the local system.
The location of the main system-wide configuration file (/etc/rawhide.conf
, or similar) can be overridden with the environment variable RAWHIDE_CONFIG
. This is only available to non-root
users (as it could be dangerous for root
). The directory containing any additional system-wide configuration files is derived from it by appending ".d"
.
The location of the main user-specific configuration file (~/.rhrc
) can be overridden with the environment variable RAWHIDE_RC
. This is only available to non-root
users (as it could be dangerous for root
). The directory containing any additional user-specific configuration files is derived from it by appending ".d"
.
rh(1), stat(2), mktime(3), fnmatch(3), glob(7), perlre(1), pcre2pattern(3), pcre2syntax(3), access(2), acl(2) or acl(3) or acl(5), xattr(1) or xattr(7) or extattr(2) or fsattr(7), chattr(1), lsattr(1), chflags(1), file(1), jq(1), The C programming language.
1990 Ken Stauffer (University of Calgary)
2022-2023 raf <raf@raf.org>