From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Michael Kerrisk (man-pages)" Subject: Re: richacl(7) man page review comments Date: Sun, 21 Feb 2016 22:40:59 +0100 Message-ID: <56CA2EEB.9080504@gmail.com> References: <56B770B6.7040803@gmail.com> <56B77262.7090107@gmail.com> <56C0F23C.7030902@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: In-Reply-To: Sender: linux-api-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Andreas Gruenbacher Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, "J. Bruce Fields" , linux-ext4 , XFS Developers , lkml , linux-fsdevel , Linux NFS Mailing List , linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API , Dave Chinner , Christoph Hellwig , Anna Schumaker , Trond Myklebust , Jeff Layton , Andreas Dilger List-Id: linux-api@vger.kernel.org Hello Andreas, On 02/20/2016 05:37 PM, Andreas Gruenbacher wrote: > Hi Michael, >=20 > thanks again for all the feedback. I've followed all your suggestions= ; > again, please see the github repo for the latest version: >=20 > https://github.com/andreas-gruenbacher/richacl I've once more pulled from the latest git; here's some more comments. > .\" > .\" RichACL Manual Pages > .\" > .\" Copyright (C) 2015,2016 Red Hat, Inc. > .\" Written by Andreas Gruenbacher > .\" This is free documentation; you can redistribute it and/or > .\" modify it under the terms of the GNU General Public License as > .\" published by the Free Software Foundation; either version 2 of > .\" the License, or (at your option) any later version. > .\" > .\" The GNU General Public License's references to "object code" > .\" and "executables" are to be interpreted as the output of any > .\" document formatting or typesetting system, including > .\" intermediate and printed output. > .\" > .\" This manual is distributed in the hope that it will be useful, > .\" but WITHOUT ANY WARRANTY; without even the implied warranty of > .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > .\" GNU General Public License for more details. > .\" > .\" You should have received a copy of the GNU General Public > .\" License along with this manual. If not, see > .\" . > .\" > .de URL > \\$2 \(laURL: \\$1 \(ra\\$3 > .. > .if \n[.g] .mso www.tmac > .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists" > .SH NAME > richacl \- Rich Access Control Lists > .SH DESCRIPTION > Rich Access Control Lists (RichACLs) are an extension of the POSIX fi= le > permission model (see > .BR acl (5)) > to support > .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lis= ts" > on local and remote-mounted filesystems. >=20 > A RichACL can always be translated into an equivalent NFSv4 ACL which= grants > the same permissions. >=20 > RichACLs can be enabled on supported local filesystems (currently, ex= t4 and > XFS). This disables POSIX Access Control Lists; the two ACL models c= annot > coexist on the same filesystem. >=20 > The in-kernel NFSv4 server and client also include RichACL support. Rewrite the preceding two paras in a better logical split and order: [[ RichACLs can be enabled on supported local filesystems (currently, ext4= and XFS). The in-kernel NFSv4 server and client also include RichACL suppo= rt. Enabling RichACLs disables POSIX Access Control Lists; the two ACL models cannot coexist on the same filesystem. ]] >=20 > When used on a filesystem that does not support RichACLs, the > .BR getrichacl (1) > and > .BR setrichacl (1) > utilities will operate on the file permission bits instead: > .BR getrichacl (1) > will display the file permission bits as a RichACL; when a RichACL > is set with > .BR setrichacl (1) > which can be represented exactly by the file permission bits, > .BR setrichacl (1) > will set the file permission bits instead. An attempt to set a RichA= CL that > cannot be represented exactly by the file permission bits results in = an error. >=20 > .SS Structure of RichACLs >=20 > RichACLs consist of a number of ACL entries, three file masks, and so= me flags s/some flags/a set of flags/ > specifying attributes of the ACL as whole (by contrast with the per-A= CL-entry s/whole/a whole/ > flags described below). >=20 > Each of the ACL entries allows or denies some permissions to a partic= ular user, > group, or special identifier. An ACL entry consists of four fields: >=20 > .IP \(bu 4 s/4/2/ > A tag which specifies the user, group, or special identifier the entr= y applies > to. Special identifiers can be the file owner, the owning group, or = everyone. =3D=3D> Special identifiers correspond to one of three file masks for the file = owner =2ERB ( owner@ ), the owning group =2ERB ( group@ ), or everyone =2ERB ( everyone@ ). > .IP \(bu > A set of permissions the entry allows or denies. > .IP \(bu > A set of flags that indicate whether the user or group identifier is = mapped or > unmapped, and whether the entry has been and can be inherited. > .IP \(bu 4 s/ 4// > A type field indicating whether the entry allows or denies access. s/access/the permissions specified in the second field/ > .PP > The owner, group, and other file masks further control which permissi= ons the > ACL grants, subject to the > .BR masked "\ (" m ) > and > .BR write_through "\ (" w ) > ACL flags: when the permissions of a file or directory are changed wi= th > .BR chmod (2), > the file masks are set based on the new file mode, and the > .B masked > and > .B write_through > ACL flags are set. Likewise, when a new file or directory inherits an= ACL from > its parent directory, the file masks are set to the intersection betw= een the > permissions granted by the inherited ACL and the > .I mode > parameter as given to > .BR open "(2), " mkdir (2), > and similar, and the > .B masked > ACL flag is set. In both cases, the file masks limit the permissions = that the > ACL will grant. >=20 > The advantage of this approach over directly modifying the ACL entrie= s is that > permissions defined in ACL entries are not lot when the file masks ar= e later s/lot/lost/ > set to be less restrictive. (I think) I know what you are trying to say in the previous paragraph, but "this approach" and "directly modifying the ACL entries" is a littl= e vague. Masks are about solving the hysteresis problem, right? So, how about some text along the following lines (I'm sure you can improve): [[ The purpose of the file masks is to allow applications that are unaware of RichACLs to place limits on the permissions granted by various classes of RichACL in a manner that corresponds to the traditional user/group/other semantics, without modifying the ACL entries in those classes. Without the file masks, the only alternative would be for the kernel to directly modify the ACL entries in those classes. However, this latter approach could have a "hysteresis effect", whereby a RichACL-unaware application that performs a transition from one file mode to another file mode and then back to the original file mode could cause destruction of the permission information in ACL entries. ]] >=20 > Note that entries with the identifier > .B everyone@ > apply to all processes, whereas the \(lqother\(rq file permissions an= d > \(lqother\(rq entries in POSIX ACLs apply to all processes which are = not the I'd be inclined to use (or add) \fBACL_OTHER\fP instead of "other" in the preceding line. Things makes things IMO a little clearer when you try to distinguish from "other" file permissions. > owner, are not in the owning group, and do not match a user or group = mentioned > in the ACL. >=20 > Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs = that > define the access permissions and \(lqdefault\(rq ACLs that define th= e > inheritable permissions. Instead, flags on each ACL entry determine = whether > the entry is effective during access checks and/or inheritable. >=20 >=20 > .SS ACL flags >=20 > The following flags on ACLs are defined: s/flags on ACLs/ACL flags/ >=20 > .TP > .BR masked "\ (" m ) > When set, the file masks define upper limits on the permissions the A= CL may > grant. When not set, the file masks are ignored. > .TP > .BR write_through "\ (" w ) > When this flag and the > .B masked > flag are both set, the owner and other file masks define the actual p= ermissions > granted to the file owner and to others instead of defining an upper = limit. > When the > .B masked > flag is not set, the write_through flag has no effect. Use .BR write_through for preceding line > .TP > .BR auto_inherit "\ (" a ) > Automatic Inheritance is enabled. See > .IR "Automatic Inheritance" . > .TP > .BR protected "\ (" p ) > The ACL is protected from modification by Automatic > Inheritance. > .TP > .BR defaulted "\ (" d ) > Indicates that the ACL has been assigned in an application-dependent = way when > the file or directory was created; it has neither been inherited nor = set > explicitly. ACLs of files created on Linux will never have the > .B defaulted > flag set.=20 The preceding sentence immediately triggers an obvious question for the reader. So, do we need a sentence here to say when/where the "defaulte= d" flag is set? > When this flag is set for an ACL, Automatic Inheritance wil= l > completely replace the ACL. >=20 > .SS ACL entry flags >=20 > The following flags on ACL entries are defined: >=20 > .TP > .BR file_inherit "\ (" f ) > When this flag appears in the ACL entry of a directory, then: > .RS > .IP \(bu 4 > That entry is inherited by new files created in the directory such th= at the s/4/2/ > permissions of the entry apply to the file (the inheritance flags of = the > inherited entry are cleared). > .IP \(bu 4 > The entry is is inherited by new subdirectories created in the direct= ory such s/ 4// > that the permissions of the entry will apply to new files created in = the > subdirectory. > .RE > .TP > .BR dir_inherit "\ (" d ) > When this flag appears in the ACL entry of a directory, then that ent= ry is > inherited by new subdirectories created in the directory such that th= e > permissions of the entry apply to the subdirectory (the > .B inherit_only > flag is cleared). > .TP > .BR no_propagate "\ (" n ) > Inheritance stops at the next subdirectory level. When a file or dir= ectory > inherits an entry that has this flag set, the > .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_= only > flags are cleared. > .TP > .BR inherit_only "\ (" i ) > The entry defines inheritable permissions only and is ignored for acc= ess > checking. When a file or directory inherits an entry that has this f= lag set, > the flag is cleared. > .TP > .BR inherited "\ (" a ) > The entry has been automatically inherited from the parent directory;= the > ACL's > .B auto_inherit > flag should be on. Why "should be" in the previous sentence? I think a little explanation is needed here... > .TP > .BR unmapped "\ (" u ) > The user or group identifier is a textual string and is not mapped to= a numeric > user or group identifier. ACLs with unmapped identifiers can occur o= n NFSv4 > mounted filesystems when the client cannot determine numeric user or = group > identifiers for some of the NFSv4 user@domain or group@domain who val= ues. They > cannot be assigned to local files or directories. >=20 > .SS Permissions >=20 > The following permissions are defined for RichACL entries and for the= three > file masks: >=20 > .TP > .BR read_data " / " list_directory "\ (" r ) > For a file: read the data of the file. > For a directory: list the contents of the directory. > .TP > .BR write_data " / " add_file "\ (" w ) > For a file: modify the data of the file; does not include opening the= file in > append mode. > For a directory: add a new file in the directory. > .TP > .BR append_data " / " add_subdirectory "\ (" p ) > For a file: open the file in append mode. > For a directory: create a subdirectory in the directory. > .TP > .BR execute "\ (" x ) > For a file: execute the file. > For a directory: traverse / search the directory. s%traverse / search%traverse (search)% > .TP > .BR delete_child "\ (" d ) > Delete a file or directory within a directory. This permission is me= aningless > for non-directories. =3D=3D> "This permission is meanungful only for directories." > .TP > .BR delete "\ (" D ) > Delete the file or directory. > .TP > .BR read_attributes "\ (" a ) > Read basic attributes of a file or directory (see > .BR stat (2)). > This permission is defined by NFSv4. It is stored, but ignored. Rea= ding basic > attributes of files and directories is always allowed on Linux. > .TP > .BR write_attributes "\ (" A ) > Change the times associated with a file or directory to an arbitrary = value. > This permission is always implicitly granted to the file owner. > .TP > .BR read_acl "\ (" c ) > Read the ACL of a file or directory. This permission is always > implicitly granted. So, I think a sentence explaining why "read_acl" exists would be helpful, since the reader is left a little puzzled about its purpose if it is always implicitly granted. > .TP > .BR write_acl "\ (" C ) > Change the ACL or file mode of a file or directory. > .TP > .BR write_owner "\ (" o ) > Take ownership of a file or directory. Change the owning group of a = file or > directory to a group of which the calling process is a member. > .TP =46ormatting tweak: add ".ad l" before the following line amd ".ad" aft= er the line. > .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " sy= nchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_h= old "\ (" E ) > These permissions are defined by NFSv4 / NFSv4.1. They are stored, b= ut ignored. s%/%and% > .PP > For the > .BR r ", " w ", and " p > permissions which have different long forms for files and directories= , the s/permissions/permissions,/ > .BR getrichacl (1) > utility will output the appropriate form(s) depending on the context. > The > .BR setrichacl (1) > utility will accept either form for any file type. >=20 > .SS Text form > The common textual representation of a RichACL consists of the colon-= separated > fields of the ACL flags, file masks, and ACL entries in the following > format: > .TP > \fBflags:\fR\fIacl_flags\fR > The ACL flags. > .TP > \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\f= R, \fBother:\fR\fIperm\fR\fB::mask\fR > The file masks and their permissions. > .TP > \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\f= B:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR > For each ACL entry, who the entry applies to, the permissions of the = entry, the > entry flags, and the entry type. The who field is one of the followin= g: s/who/\\fIwho\\fP/ > .RS > .IP \(bu 4 s/4/2/ > One of the special identifiers: > .BR owner@ ", " group@ ", or " everyone@ , > .IP \(bu > A > .BR user: " or " u: > prefix followed by a user name or user ID that designates a specific = user, > .IP \(bu > A > .BR group: " or " g: > prefix followed by a group name or group ID that designates a specifi= c group. > .RE > .PP > The entries are comma, whitespace, or newline separated. >=20 > Flags and permissions have single-letter as well as long forms, as li= sted under > .IR "ACL flags" , > .IR "ACL entry flags" , > and > .IR Permissions . > When the single-letter forms are used, the flags or permissions are > concatenated. When the long forms are used, the flags or permissions = are > separated by slashes. To align permissions or flags vertically, dash= es can be > used for padding. >=20 > .SS Setting and modifying file permissions > The access permissions for a file can either be set by assigning an A= ccess > Control List > .RB ( setrichacl (1)) > or by changing the file mode permission bits > .RB ( chmod (1)). > In addition, a file can inherit an ACL from its parent directory at c= reation > time as described under > .IR "Permissions at file-creation time" . >=20 > .SS Assigning an Access Control List > When assigning an ACL to a file, unless explicitly specified, the own= er, group, > and other file masks will be computed from the ACL entries as describ= ed in > the section > .IR "Computing the maximum file masks" . > The owner, group, and other file mode permission bits are then each s= et from > the owner, group, and other file mask as follows: > .IP \(bu 4 s/4/2/ > If the file mask includes the > .B r > permission, the read > file mode permission bit will be set. > .IP \(bu > If the file mask includes the > .B w > or > .B p > permission, the write file mode permission bit will be set. > .IP \(bu > If the file mask includes the > .B x > permission, the execute file mode permission bit will be set. > .PP > If the ACL can be represented exactly by the file mode > permission bits, the file permission bits are set to match the ACL an= d the ACL > is not stored. Maybe better: "...and no ACL is stored" > (When the ACL of a file is requested which doesn't hav= e an ACL, > the file mode permission bits are converted into an equivalent ACL.) >=20 > .SS Changing the file mode permission bits > When changing the file mode permission bits with > .BR chmod (1), > the owner, group, and other file permission bits are set to the permi= ssion bits > in the new mode, and the owner, group, and other file masks are set b= ased on > the new mode bits as follows: > .IP \(bu 4 s/4/2/ > If the read bit in a set of permissions is set, the > .B r > permission in the corresponding file mask will be set. > .IP \(bu > If the write bit in a set of permissions is set, the > .B w > and > .B p > permissions in the corresponding file mask will be set. > .IP \(bu > If the execute bit in a set of permissions is set, the > .B x > permission in the corresponding file mask will be set. > .PP > In addition, the > .B masked > and > .B write_through > ACL flags are set. This has the > effect of limiting the permissions granted by the ACL to the file mod= e > permission bits; in addition, the owner is granted the owner mode bit= s and > others are granted the other mode bits. If the > .B auto_inherit > flag is set, the > .B protected > flag is also set to prevent the Automatic Inheritance algorithm from = modifying > the ACL. >=20 > .SS Permissions at file-creation time > When a directory has inheritable ACL entries, the following s/has/has an/ > happens when a file or directory is created inside that directory: > .RS 4 > .IP 1. 4 > A file created inside that directory will inherit all of the ACL entr= ies that > have the > .B file_inherit > flag set, and all inheritance-related flags in the inherited entries = flag will > be cleared. >=20 > A subdirectory created inside that directory will inherit all of the = ACL > entries that either have the > .B dir_inherit > flag set, or the > .B file_inherit > flag set and the > .B no_propagate > flag not set. Entries whose > .B dir_inherit > flag is set will have their > .B inherit_only > flag cleared, and entries whose > .B dir_inherit > flag is not set will have their > .B inherit_only > flag set. Finally, entries whose > .B no_propagate > flag is set will have all inheritance-related flags cleared. > .IP 2. > If the parent directory's ACL has the > .B auto_inherit > flag set, the inherited ACL will have its > .B auto_inherit > flag set, and all entries will have their > .B inherited > flag set. Otherwise, the > .B auto_inherit > and > .B inherited > flags are cleared. > .IP 3. > The three file masks are computed from the inherited ACL as described= in > the section > .IR "Computing the maximum file masks" . > .IP 4. > The three sets of permissions for the owner, the group, and for other= s in > the \fImode\fR parameter as given to > .BR open (2), > .BR mkdir (2), > and similar are converted into sets of RichACL permissions. The corre= spondence > between mask flags and RichACL permission bits is described in the se= ction > .IR "Changing the file mode permission bits" . > Any RichACL permissions not included in those sets are > removed from the owner, group, and other file masks. The file mode pe= rmission > bits are then computed from the file masks as described in the sectio= n > .IR "Assigning an Access Control List" . > The process umask (see > .BR umask (2)) > is ignored. > .IP 5. > The > .B masked > ACL flag is set. The > .B write_through > ACL flag remains cleared. In addition, if the > .B auto_inherit > flag of the inherited ACL is set, the > .B protected > flag is also set to prevent the Automatic Inheritance algorithm from = modifying > the ACL. > .RE > .PP > When a directory does not have inheritable ACL entries, files and dir= ectories > created inside that directory will not be assigned Access Control Lis= ts and the > file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR= ) where > \fImode\fR is the mode argument of the relevant system call and \fIum= ask\fR is > the process umask (see > .BR umask (2)). >=20 > .SS Automatic Inheritance > Automatic Inheritance is a mechanism that allows permission changes t= o > propagate from a directory to files and subdirectories inside that di= rectory, > recursively. Propagation is carried out by the process changing the = directory > permissions (usually, > .BR setrichacl (1)); > it happens without user intervention albeit not entirely automaticall= y. >=20 > A significant limitation is that this mechanism works only as long as= files > are created without explicitly specifying the file permissions to use= =2E The > standard system calls for creating files and directories > .RB ( creat (2), > .BR open (2), > .BR mkdir (2), > .BR mknod (2)) > all have mandatory mode parameters which define the maximum allowed p= ermissions > of the new files. To take account of this restriction, the > .B protected > ACL flag must be set if the > .B inherited > flag is set. This effectively disables Automatic Inheritance for that > particular file. >=20 Add the following at the start of the next paragraph: "Motwithstanding the aforementioned limitation," > Automatic Inheritance still remains useful for network protocols like= NFSv4 and > SMB, which both support creating files and directories without defini= ng their > permissions: they can implement those operations by using the standar= d system s/: they/. These protocols/ (To avoid an excessively long sentence.) > calls and by then undoing the effect of applying the mode parameters. >=20 > When the ACL of a directory is changed, the following happens for eac= h entry > (\(lqchild\(rq) inside that directory: > .IP 1. 4 > If the entry is a symblic link, skip the child. s/symblic/symbolic/ > .IP 2. > If the > .B auto_inherit > flag of the entry's ACL is not set or the > .B protected > flag is set, skip the child. > .IP 3. > With the child's ACL: > .RS 4 > .IP a) 4 > If the > .B defaulted > flag is set, replace the ACL with an empty ACL > with the > .B auto_inherit > flag set. > .IP b) > Delete all entries which have the > .B inherited > flag set. > .IP c) > Append all entries inherited from the parent directory according to s= tep 1 of > the algorithm described under > .IR "Permissions at file-creation time". > Set the > .B inherited > flag of each of these entries. > .IP d) > Recompute the file masks. > .RE > .IP 4. > If the child is a directory, recursively apply this algorithm. >=20 > .SS Access check algorithm >=20 > When a process requests a particular kind of access (expressed as a s= et of > RichACL permissions) to a file, the following algorithm determines wh= ether the > access is granted or denied: >=20 > .IP 1. 4 > If the > .B masked > ACL flag is set, then: > .RS 4 > .IP a) 4 > If the > .B write_through > ACL flag is set, then: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the requesting process is the file owner, then access is granted i= f the > owner mask includes the requested permissions, and is otherwise denie= d. > .IP \(bu > If the requesting process is not the file owner, is not in the owning= group, > and no ACL entries other than > .B everyone@ > match the process, then access is granted if the other mask includes = the > requested permissions, and is otherwise denied. So, in the above subcases, the following does not seem to be covered: (1) "masked" ACL flag is set AND (2) requesting process *is* in owning group *or* an ACL other than "everyone@"matches the process. What happens in this case? I suspect that somehow we are supposed to fall through to part "b)" below (and possibly into clause "2."?), but the logical structure of the clauses does not reflect this. =20 > .RE > .IP b) > If any of the following is true: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > the requesting process is the file owner and the owner mask does not = include all > requested permissions, > .IP \(bu 4 s/ 4// > the requesting process is not the file owner and it is in the owning = group or > matches any ACL entries other than > .BR everyone@ , > and the group mask does not include all requested permissions, > .IP \(bu 4 s/ 4// > the requesting process is not the file owner, not in the owning group= , it > matches no ACL entries other than > .BR everyone@ , > and the other mask does not include all requested permissions, > .PP > then access is denied. > .RE > .RE At some point, perhaps in the next paragraph, I think that it needs to be clarified that unlike POSIX ACLs, a process can gain the permissions it requires by accumulating them from multiple RichACL enties. (That's correct, is it not?) > .IP 2. > Set the remaining permissions to the requested permissions. Go throu= gh all ACL > entries. For each entry: So, perhaps replace the preceding two lines with something like: [[ Upon reaching this point, the determination of whether or not access is granted is made by scanning all ACL entries to see if one or more applicable entries together grant a cumulative set of permissions that matches the requested permissions or there is an applicable entry that explicitly denies one or more of the requested permissions. The scan of all ACL entries begins by first initializing the set of remaining permissions (i.e., those that h= ave not yet been satisfied during the scan) to be the set of requested permissions. Then the ACL entries are scanned =2EIR "in order" , and for each entry: ]] > .RS 4 > .IP a) 4 > If the > .B inherit_only > or > .B unmapped > flags are set, continue with the next ACL entry. > .IP b) > If any of the following is true: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > the entry's identifier is > .B owner@ > and the requesting process is the file owner, > .IP \(bu > the entry's identifier is > .B group@ > and the requesting process is in the owning group, > .IP \(bu > the entry's identifier is a user and the requesting process is owned = by that > user, > .IP \(bu > the entry's identifier is a group and the requesting process is a mem= ber in > that group, > .IP \(bu > the entry's identifier is > .BR everyone@ , > .PP > then the entry matches the process; proceed to the next step. Otherwi= se, > continue with the next ACL entry. > .RE > .IP c) > If the entry denies any of the remaining permissions, access is denie= d. > .IP d) > If the entry allows any of the remaining permissions, then: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the > .B masked > ACL flag is set and the entry's identifier is not > .B owner@ > or > .BR everyone@ > or is a user entry matching the file owner, remove all permissions fr= om the > remaining permissions which are both allowed by the entry and include= d in the > group mask, > .IP \(bu > Otherwise, remove all permissions from the remaining permissions wich= are s/wich/which=20 > allowed by the entry. > .RE > .RE > .IP 3. > If there are no more remaining permissions, access is allowed. Otherw= ise, > access is denied. >=20 > .SS Computing the maximum file masks > When setting an ACL and no file masks have been explicitly specified = and when > inheriting an ACL from the parent directory, the following algorithm = is used > for computing the file masks: >=20 > .IP 1. 4 > Clear the owner, group, and other file masks. Remember which permissi= ons have > already been processed (initially, the empty set). > .IP 2. > For each ACL entry: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the > .B inherit_only > flag is set, skip the entry. > .IP \(bu 4 s/ 4// > Otherwise, compute which permissions the entry allows or denies that = have not > been processed yet (the remaining permissions). > .IP \(bu > If the entry is an > .B owner@ > entry, add the remaining permissions to the owner mask for > .B allow > entries, and remove the remaining permissions from the owner mask for > .B deny > entries. > .IP \(bu > Otherwise, if the entry is an > .B everyone@ > entry, proceed as with > .B owner@ > entries but add or remove the remaining permissions from the owner, g= roup, and > other file masks. > .IP \(bu > Otherwise, proceed as with > .B owner@ > entries but add or remove the remaining permissions from the owner an= d group > file masks. > .IP \(bu > Add the entry's permissions to the processed permissions. > .RE > .PP > The resulting file masks represent the ACL as closely as possible. Wi= th these > file masks, if the > .B masked > ACL flag is set, the effective permissions still stay the same. The meaing of "will stay the same" is not quite clear "will stay the same *as what*"?). I suspect I know what you mean, but it needs to be made more obvious. >=20 > .\" .SH BUGS > .SH AUTHOR > Written by Andreas Gr=C3=BCnbacher . >=20 > Please send your bug reports, suggested features and comments to the = above address. >=20 I'm going to play the broken record :-) Could we start with just a few simple examples already, and build up over future iterations of this page? > .SH CONFORMING TO > Rich Access Control Lists are Linux-specific. > .SH SEE ALSO > .BR acl (5), Move this entry to the point XXX below. > .BR chmod (1), > .BR getrichacl (1), > .BR ls (1), > .BR setrichacl (1) > .BR stat (2), > .BR umask (2) > .\" librichacl XXX By the way, are there already man pages for the librichacl functions? Cheers, Michael --=20 Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f46.google.com ([74.125.82.46]:38586 "EHLO mail-wm0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750708AbcBUVlH (ORCPT ); Sun, 21 Feb 2016 16:41:07 -0500 Subject: Re: richacl(7) man page review comments To: Andreas Gruenbacher References: <56B770B6.7040803@gmail.com> <56B77262.7090107@gmail.com> <56C0F23C.7030902@gmail.com> Cc: mtk.manpages@gmail.com, "J. Bruce Fields" , linux-ext4 , XFS Developers , lkml , linux-fsdevel , Linux NFS Mailing List , linux-cifs@vger.kernel.org, Linux API , Dave Chinner , Christoph Hellwig , Anna Schumaker , Trond Myklebust , Jeff Layton , Andreas Dilger From: "Michael Kerrisk (man-pages)" Message-ID: <56CA2EEB.9080504@gmail.com> Date: Sun, 21 Feb 2016 22:40:59 +0100 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Sender: linux-nfs-owner@vger.kernel.org List-ID: Hello Andreas, On 02/20/2016 05:37 PM, Andreas Gruenbacher wrote: > Hi Michael, > > thanks again for all the feedback. I've followed all your suggestions; > again, please see the github repo for the latest version: > > https://github.com/andreas-gruenbacher/richacl I've once more pulled from the latest git; here's some more comments. > .\" > .\" RichACL Manual Pages > .\" > .\" Copyright (C) 2015,2016 Red Hat, Inc. > .\" Written by Andreas Gruenbacher > .\" This is free documentation; you can redistribute it and/or > .\" modify it under the terms of the GNU General Public License as > .\" published by the Free Software Foundation; either version 2 of > .\" the License, or (at your option) any later version. > .\" > .\" The GNU General Public License's references to "object code" > .\" and "executables" are to be interpreted as the output of any > .\" document formatting or typesetting system, including > .\" intermediate and printed output. > .\" > .\" This manual is distributed in the hope that it will be useful, > .\" but WITHOUT ANY WARRANTY; without even the implied warranty of > .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > .\" GNU General Public License for more details. > .\" > .\" You should have received a copy of the GNU General Public > .\" License along with this manual. If not, see > .\" . > .\" > .de URL > \\$2 \(laURL: \\$1 \(ra\\$3 > .. > .if \n[.g] .mso www.tmac > .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists" > .SH NAME > richacl \- Rich Access Control Lists > .SH DESCRIPTION > Rich Access Control Lists (RichACLs) are an extension of the POSIX file > permission model (see > .BR acl (5)) > to support > .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists" > on local and remote-mounted filesystems. > > A RichACL can always be translated into an equivalent NFSv4 ACL which grants > the same permissions. > > RichACLs can be enabled on supported local filesystems (currently, ext4 and > XFS). This disables POSIX Access Control Lists; the two ACL models cannot > coexist on the same filesystem. > > The in-kernel NFSv4 server and client also include RichACL support. Rewrite the preceding two paras in a better logical split and order: [[ RichACLs can be enabled on supported local filesystems (currently, ext4 and XFS). The in-kernel NFSv4 server and client also include RichACL support. Enabling RichACLs disables POSIX Access Control Lists; the two ACL models cannot coexist on the same filesystem. ]] > > When used on a filesystem that does not support RichACLs, the > .BR getrichacl (1) > and > .BR setrichacl (1) > utilities will operate on the file permission bits instead: > .BR getrichacl (1) > will display the file permission bits as a RichACL; when a RichACL > is set with > .BR setrichacl (1) > which can be represented exactly by the file permission bits, > .BR setrichacl (1) > will set the file permission bits instead. An attempt to set a RichACL that > cannot be represented exactly by the file permission bits results in an error. > > .SS Structure of RichACLs > > RichACLs consist of a number of ACL entries, three file masks, and some flags s/some flags/a set of flags/ > specifying attributes of the ACL as whole (by contrast with the per-ACL-entry s/whole/a whole/ > flags described below). > > Each of the ACL entries allows or denies some permissions to a particular user, > group, or special identifier. An ACL entry consists of four fields: > > .IP \(bu 4 s/4/2/ > A tag which specifies the user, group, or special identifier the entry applies > to. Special identifiers can be the file owner, the owning group, or everyone. ==> Special identifiers correspond to one of three file masks for the file owner .RB ( owner@ ), the owning group .RB ( group@ ), or everyone .RB ( everyone@ ). > .IP \(bu > A set of permissions the entry allows or denies. > .IP \(bu > A set of flags that indicate whether the user or group identifier is mapped or > unmapped, and whether the entry has been and can be inherited. > .IP \(bu 4 s/ 4// > A type field indicating whether the entry allows or denies access. s/access/the permissions specified in the second field/ > .PP > The owner, group, and other file masks further control which permissions the > ACL grants, subject to the > .BR masked "\ (" m ) > and > .BR write_through "\ (" w ) > ACL flags: when the permissions of a file or directory are changed with > .BR chmod (2), > the file masks are set based on the new file mode, and the > .B masked > and > .B write_through > ACL flags are set. Likewise, when a new file or directory inherits an ACL from > its parent directory, the file masks are set to the intersection between the > permissions granted by the inherited ACL and the > .I mode > parameter as given to > .BR open "(2), " mkdir (2), > and similar, and the > .B masked > ACL flag is set. In both cases, the file masks limit the permissions that the > ACL will grant. > > The advantage of this approach over directly modifying the ACL entries is that > permissions defined in ACL entries are not lot when the file masks are later s/lot/lost/ > set to be less restrictive. (I think) I know what you are trying to say in the previous paragraph, but "this approach" and "directly modifying the ACL entries" is a little vague. Masks are about solving the hysteresis problem, right? So, how about some text along the following lines (I'm sure you can improve): [[ The purpose of the file masks is to allow applications that are unaware of RichACLs to place limits on the permissions granted by various classes of RichACL in a manner that corresponds to the traditional user/group/other semantics, without modifying the ACL entries in those classes. Without the file masks, the only alternative would be for the kernel to directly modify the ACL entries in those classes. However, this latter approach could have a "hysteresis effect", whereby a RichACL-unaware application that performs a transition from one file mode to another file mode and then back to the original file mode could cause destruction of the permission information in ACL entries. ]] > > Note that entries with the identifier > .B everyone@ > apply to all processes, whereas the \(lqother\(rq file permissions and > \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the I'd be inclined to use (or add) \fBACL_OTHER\fP instead of "other" in the preceding line. Things makes things IMO a little clearer when you try to distinguish from "other" file permissions. > owner, are not in the owning group, and do not match a user or group mentioned > in the ACL. > > Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that > define the access permissions and \(lqdefault\(rq ACLs that define the > inheritable permissions. Instead, flags on each ACL entry determine whether > the entry is effective during access checks and/or inheritable. > > > .SS ACL flags > > The following flags on ACLs are defined: s/flags on ACLs/ACL flags/ > > .TP > .BR masked "\ (" m ) > When set, the file masks define upper limits on the permissions the ACL may > grant. When not set, the file masks are ignored. > .TP > .BR write_through "\ (" w ) > When this flag and the > .B masked > flag are both set, the owner and other file masks define the actual permissions > granted to the file owner and to others instead of defining an upper limit. > When the > .B masked > flag is not set, the write_through flag has no effect. Use .BR write_through for preceding line > .TP > .BR auto_inherit "\ (" a ) > Automatic Inheritance is enabled. See > .IR "Automatic Inheritance" . > .TP > .BR protected "\ (" p ) > The ACL is protected from modification by Automatic > Inheritance. > .TP > .BR defaulted "\ (" d ) > Indicates that the ACL has been assigned in an application-dependent way when > the file or directory was created; it has neither been inherited nor set > explicitly. ACLs of files created on Linux will never have the > .B defaulted > flag set. The preceding sentence immediately triggers an obvious question for the reader. So, do we need a sentence here to say when/where the "defaulted" flag is set? > When this flag is set for an ACL, Automatic Inheritance will > completely replace the ACL. > > .SS ACL entry flags > > The following flags on ACL entries are defined: > > .TP > .BR file_inherit "\ (" f ) > When this flag appears in the ACL entry of a directory, then: > .RS > .IP \(bu 4 > That entry is inherited by new files created in the directory such that the s/4/2/ > permissions of the entry apply to the file (the inheritance flags of the > inherited entry are cleared). > .IP \(bu 4 > The entry is is inherited by new subdirectories created in the directory such s/ 4// > that the permissions of the entry will apply to new files created in the > subdirectory. > .RE > .TP > .BR dir_inherit "\ (" d ) > When this flag appears in the ACL entry of a directory, then that entry is > inherited by new subdirectories created in the directory such that the > permissions of the entry apply to the subdirectory (the > .B inherit_only > flag is cleared). > .TP > .BR no_propagate "\ (" n ) > Inheritance stops at the next subdirectory level. When a file or directory > inherits an entry that has this flag set, the > .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_only > flags are cleared. > .TP > .BR inherit_only "\ (" i ) > The entry defines inheritable permissions only and is ignored for access > checking. When a file or directory inherits an entry that has this flag set, > the flag is cleared. > .TP > .BR inherited "\ (" a ) > The entry has been automatically inherited from the parent directory; the > ACL's > .B auto_inherit > flag should be on. Why "should be" in the previous sentence? I think a little explanation is needed here... > .TP > .BR unmapped "\ (" u ) > The user or group identifier is a textual string and is not mapped to a numeric > user or group identifier. ACLs with unmapped identifiers can occur on NFSv4 > mounted filesystems when the client cannot determine numeric user or group > identifiers for some of the NFSv4 user@domain or group@domain who values. They > cannot be assigned to local files or directories. > > .SS Permissions > > The following permissions are defined for RichACL entries and for the three > file masks: > > .TP > .BR read_data " / " list_directory "\ (" r ) > For a file: read the data of the file. > For a directory: list the contents of the directory. > .TP > .BR write_data " / " add_file "\ (" w ) > For a file: modify the data of the file; does not include opening the file in > append mode. > For a directory: add a new file in the directory. > .TP > .BR append_data " / " add_subdirectory "\ (" p ) > For a file: open the file in append mode. > For a directory: create a subdirectory in the directory. > .TP > .BR execute "\ (" x ) > For a file: execute the file. > For a directory: traverse / search the directory. s%traverse / search%traverse (search)% > .TP > .BR delete_child "\ (" d ) > Delete a file or directory within a directory. This permission is meaningless > for non-directories. ==> "This permission is meanungful only for directories." > .TP > .BR delete "\ (" D ) > Delete the file or directory. > .TP > .BR read_attributes "\ (" a ) > Read basic attributes of a file or directory (see > .BR stat (2)). > This permission is defined by NFSv4. It is stored, but ignored. Reading basic > attributes of files and directories is always allowed on Linux. > .TP > .BR write_attributes "\ (" A ) > Change the times associated with a file or directory to an arbitrary value. > This permission is always implicitly granted to the file owner. > .TP > .BR read_acl "\ (" c ) > Read the ACL of a file or directory. This permission is always > implicitly granted. So, I think a sentence explaining why "read_acl" exists would be helpful, since the reader is left a little puzzled about its purpose if it is always implicitly granted. > .TP > .BR write_acl "\ (" C ) > Change the ACL or file mode of a file or directory. > .TP > .BR write_owner "\ (" o ) > Take ownership of a file or directory. Change the owning group of a file or > directory to a group of which the calling process is a member. > .TP Formatting tweak: add ".ad l" before the following line amd ".ad" after the line. > .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " synchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_hold "\ (" E ) > These permissions are defined by NFSv4 / NFSv4.1. They are stored, but ignored. s%/%and% > .PP > For the > .BR r ", " w ", and " p > permissions which have different long forms for files and directories, the s/permissions/permissions,/ > .BR getrichacl (1) > utility will output the appropriate form(s) depending on the context. > The > .BR setrichacl (1) > utility will accept either form for any file type. > > .SS Text form > The common textual representation of a RichACL consists of the colon-separated > fields of the ACL flags, file masks, and ACL entries in the following > format: > .TP > \fBflags:\fR\fIacl_flags\fR > The ACL flags. > .TP > \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR > The file masks and their permissions. > .TP > \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR > For each ACL entry, who the entry applies to, the permissions of the entry, the > entry flags, and the entry type. The who field is one of the following: s/who/\\fIwho\\fP/ > .RS > .IP \(bu 4 s/4/2/ > One of the special identifiers: > .BR owner@ ", " group@ ", or " everyone@ , > .IP \(bu > A > .BR user: " or " u: > prefix followed by a user name or user ID that designates a specific user, > .IP \(bu > A > .BR group: " or " g: > prefix followed by a group name or group ID that designates a specific group. > .RE > .PP > The entries are comma, whitespace, or newline separated. > > Flags and permissions have single-letter as well as long forms, as listed under > .IR "ACL flags" , > .IR "ACL entry flags" , > and > .IR Permissions . > When the single-letter forms are used, the flags or permissions are > concatenated. When the long forms are used, the flags or permissions are > separated by slashes. To align permissions or flags vertically, dashes can be > used for padding. > > .SS Setting and modifying file permissions > The access permissions for a file can either be set by assigning an Access > Control List > .RB ( setrichacl (1)) > or by changing the file mode permission bits > .RB ( chmod (1)). > In addition, a file can inherit an ACL from its parent directory at creation > time as described under > .IR "Permissions at file-creation time" . > > .SS Assigning an Access Control List > When assigning an ACL to a file, unless explicitly specified, the owner, group, > and other file masks will be computed from the ACL entries as described in > the section > .IR "Computing the maximum file masks" . > The owner, group, and other file mode permission bits are then each set from > the owner, group, and other file mask as follows: > .IP \(bu 4 s/4/2/ > If the file mask includes the > .B r > permission, the read > file mode permission bit will be set. > .IP \(bu > If the file mask includes the > .B w > or > .B p > permission, the write file mode permission bit will be set. > .IP \(bu > If the file mask includes the > .B x > permission, the execute file mode permission bit will be set. > .PP > If the ACL can be represented exactly by the file mode > permission bits, the file permission bits are set to match the ACL and the ACL > is not stored. Maybe better: "...and no ACL is stored" > (When the ACL of a file is requested which doesn't have an ACL, > the file mode permission bits are converted into an equivalent ACL.) > > .SS Changing the file mode permission bits > When changing the file mode permission bits with > .BR chmod (1), > the owner, group, and other file permission bits are set to the permission bits > in the new mode, and the owner, group, and other file masks are set based on > the new mode bits as follows: > .IP \(bu 4 s/4/2/ > If the read bit in a set of permissions is set, the > .B r > permission in the corresponding file mask will be set. > .IP \(bu > If the write bit in a set of permissions is set, the > .B w > and > .B p > permissions in the corresponding file mask will be set. > .IP \(bu > If the execute bit in a set of permissions is set, the > .B x > permission in the corresponding file mask will be set. > .PP > In addition, the > .B masked > and > .B write_through > ACL flags are set. This has the > effect of limiting the permissions granted by the ACL to the file mode > permission bits; in addition, the owner is granted the owner mode bits and > others are granted the other mode bits. If the > .B auto_inherit > flag is set, the > .B protected > flag is also set to prevent the Automatic Inheritance algorithm from modifying > the ACL. > > .SS Permissions at file-creation time > When a directory has inheritable ACL entries, the following s/has/has an/ > happens when a file or directory is created inside that directory: > .RS 4 > .IP 1. 4 > A file created inside that directory will inherit all of the ACL entries that > have the > .B file_inherit > flag set, and all inheritance-related flags in the inherited entries flag will > be cleared. > > A subdirectory created inside that directory will inherit all of the ACL > entries that either have the > .B dir_inherit > flag set, or the > .B file_inherit > flag set and the > .B no_propagate > flag not set. Entries whose > .B dir_inherit > flag is set will have their > .B inherit_only > flag cleared, and entries whose > .B dir_inherit > flag is not set will have their > .B inherit_only > flag set. Finally, entries whose > .B no_propagate > flag is set will have all inheritance-related flags cleared. > .IP 2. > If the parent directory's ACL has the > .B auto_inherit > flag set, the inherited ACL will have its > .B auto_inherit > flag set, and all entries will have their > .B inherited > flag set. Otherwise, the > .B auto_inherit > and > .B inherited > flags are cleared. > .IP 3. > The three file masks are computed from the inherited ACL as described in > the section > .IR "Computing the maximum file masks" . > .IP 4. > The three sets of permissions for the owner, the group, and for others in > the \fImode\fR parameter as given to > .BR open (2), > .BR mkdir (2), > and similar are converted into sets of RichACL permissions. The correspondence > between mask flags and RichACL permission bits is described in the section > .IR "Changing the file mode permission bits" . > Any RichACL permissions not included in those sets are > removed from the owner, group, and other file masks. The file mode permission > bits are then computed from the file masks as described in the section > .IR "Assigning an Access Control List" . > The process umask (see > .BR umask (2)) > is ignored. > .IP 5. > The > .B masked > ACL flag is set. The > .B write_through > ACL flag remains cleared. In addition, if the > .B auto_inherit > flag of the inherited ACL is set, the > .B protected > flag is also set to prevent the Automatic Inheritance algorithm from modifying > the ACL. > .RE > .PP > When a directory does not have inheritable ACL entries, files and directories > created inside that directory will not be assigned Access Control Lists and the > file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where > \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is > the process umask (see > .BR umask (2)). > > .SS Automatic Inheritance > Automatic Inheritance is a mechanism that allows permission changes to > propagate from a directory to files and subdirectories inside that directory, > recursively. Propagation is carried out by the process changing the directory > permissions (usually, > .BR setrichacl (1)); > it happens without user intervention albeit not entirely automatically. > > A significant limitation is that this mechanism works only as long as files > are created without explicitly specifying the file permissions to use. The > standard system calls for creating files and directories > .RB ( creat (2), > .BR open (2), > .BR mkdir (2), > .BR mknod (2)) > all have mandatory mode parameters which define the maximum allowed permissions > of the new files. To take account of this restriction, the > .B protected > ACL flag must be set if the > .B inherited > flag is set. This effectively disables Automatic Inheritance for that > particular file. > Add the following at the start of the next paragraph: "Motwithstanding the aforementioned limitation," > Automatic Inheritance still remains useful for network protocols like NFSv4 and > SMB, which both support creating files and directories without defining their > permissions: they can implement those operations by using the standard system s/: they/. These protocols/ (To avoid an excessively long sentence.) > calls and by then undoing the effect of applying the mode parameters. > > When the ACL of a directory is changed, the following happens for each entry > (\(lqchild\(rq) inside that directory: > .IP 1. 4 > If the entry is a symblic link, skip the child. s/symblic/symbolic/ > .IP 2. > If the > .B auto_inherit > flag of the entry's ACL is not set or the > .B protected > flag is set, skip the child. > .IP 3. > With the child's ACL: > .RS 4 > .IP a) 4 > If the > .B defaulted > flag is set, replace the ACL with an empty ACL > with the > .B auto_inherit > flag set. > .IP b) > Delete all entries which have the > .B inherited > flag set. > .IP c) > Append all entries inherited from the parent directory according to step 1 of > the algorithm described under > .IR "Permissions at file-creation time". > Set the > .B inherited > flag of each of these entries. > .IP d) > Recompute the file masks. > .RE > .IP 4. > If the child is a directory, recursively apply this algorithm. > > .SS Access check algorithm > > When a process requests a particular kind of access (expressed as a set of > RichACL permissions) to a file, the following algorithm determines whether the > access is granted or denied: > > .IP 1. 4 > If the > .B masked > ACL flag is set, then: > .RS 4 > .IP a) 4 > If the > .B write_through > ACL flag is set, then: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the requesting process is the file owner, then access is granted if the > owner mask includes the requested permissions, and is otherwise denied. > .IP \(bu > If the requesting process is not the file owner, is not in the owning group, > and no ACL entries other than > .B everyone@ > match the process, then access is granted if the other mask includes the > requested permissions, and is otherwise denied. So, in the above subcases, the following does not seem to be covered: (1) "masked" ACL flag is set AND (2) requesting process *is* in owning group *or* an ACL other than "everyone@"matches the process. What happens in this case? I suspect that somehow we are supposed to fall through to part "b)" below (and possibly into clause "2."?), but the logical structure of the clauses does not reflect this. > .RE > .IP b) > If any of the following is true: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > the requesting process is the file owner and the owner mask does not include all > requested permissions, > .IP \(bu 4 s/ 4// > the requesting process is not the file owner and it is in the owning group or > matches any ACL entries other than > .BR everyone@ , > and the group mask does not include all requested permissions, > .IP \(bu 4 s/ 4// > the requesting process is not the file owner, not in the owning group, it > matches no ACL entries other than > .BR everyone@ , > and the other mask does not include all requested permissions, > .PP > then access is denied. > .RE > .RE At some point, perhaps in the next paragraph, I think that it needs to be clarified that unlike POSIX ACLs, a process can gain the permissions it requires by accumulating them from multiple RichACL enties. (That's correct, is it not?) > .IP 2. > Set the remaining permissions to the requested permissions. Go through all ACL > entries. For each entry: So, perhaps replace the preceding two lines with something like: [[ Upon reaching this point, the determination of whether or not access is granted is made by scanning all ACL entries to see if one or more applicable entries together grant a cumulative set of permissions that matches the requested permissions or there is an applicable entry that explicitly denies one or more of the requested permissions. The scan of all ACL entries begins by first initializing the set of remaining permissions (i.e., those that have not yet been satisfied during the scan) to be the set of requested permissions. Then the ACL entries are scanned .IR "in order" , and for each entry: ]] > .RS 4 > .IP a) 4 > If the > .B inherit_only > or > .B unmapped > flags are set, continue with the next ACL entry. > .IP b) > If any of the following is true: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > the entry's identifier is > .B owner@ > and the requesting process is the file owner, > .IP \(bu > the entry's identifier is > .B group@ > and the requesting process is in the owning group, > .IP \(bu > the entry's identifier is a user and the requesting process is owned by that > user, > .IP \(bu > the entry's identifier is a group and the requesting process is a member in > that group, > .IP \(bu > the entry's identifier is > .BR everyone@ , > .PP > then the entry matches the process; proceed to the next step. Otherwise, > continue with the next ACL entry. > .RE > .IP c) > If the entry denies any of the remaining permissions, access is denied. > .IP d) > If the entry allows any of the remaining permissions, then: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the > .B masked > ACL flag is set and the entry's identifier is not > .B owner@ > or > .BR everyone@ > or is a user entry matching the file owner, remove all permissions from the > remaining permissions which are both allowed by the entry and included in the > group mask, > .IP \(bu > Otherwise, remove all permissions from the remaining permissions wich are s/wich/which > allowed by the entry. > .RE > .RE > .IP 3. > If there are no more remaining permissions, access is allowed. Otherwise, > access is denied. > > .SS Computing the maximum file masks > When setting an ACL and no file masks have been explicitly specified and when > inheriting an ACL from the parent directory, the following algorithm is used > for computing the file masks: > > .IP 1. 4 > Clear the owner, group, and other file masks. Remember which permissions have > already been processed (initially, the empty set). > .IP 2. > For each ACL entry: > .RS 4 s/4/2/ > .IP \(bu 4 s/4/2/ > If the > .B inherit_only > flag is set, skip the entry. > .IP \(bu 4 s/ 4// > Otherwise, compute which permissions the entry allows or denies that have not > been processed yet (the remaining permissions). > .IP \(bu > If the entry is an > .B owner@ > entry, add the remaining permissions to the owner mask for > .B allow > entries, and remove the remaining permissions from the owner mask for > .B deny > entries. > .IP \(bu > Otherwise, if the entry is an > .B everyone@ > entry, proceed as with > .B owner@ > entries but add or remove the remaining permissions from the owner, group, and > other file masks. > .IP \(bu > Otherwise, proceed as with > .B owner@ > entries but add or remove the remaining permissions from the owner and group > file masks. > .IP \(bu > Add the entry's permissions to the processed permissions. > .RE > .PP > The resulting file masks represent the ACL as closely as possible. With these > file masks, if the > .B masked > ACL flag is set, the effective permissions still stay the same. The meaing of "will stay the same" is not quite clear "will stay the same *as what*"?). I suspect I know what you mean, but it needs to be made more obvious. > > .\" .SH BUGS > .SH AUTHOR > Written by Andreas Grünbacher . > > Please send your bug reports, suggested features and comments to the above address. > I'm going to play the broken record :-) Could we start with just a few simple examples already, and build up over future iterations of this page? > .SH CONFORMING TO > Rich Access Control Lists are Linux-specific. > .SH SEE ALSO > .BR acl (5), Move this entry to the point XXX below. > .BR chmod (1), > .BR getrichacl (1), > .BR ls (1), > .BR setrichacl (1) > .BR stat (2), > .BR umask (2) > .\" librichacl XXX By the way, are there already man pages for the librichacl functions? Cheers, Michael -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 015B27CBD for ; Sun, 21 Feb 2016 15:41:20 -0600 (CST) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B1CF2304097 for ; Sun, 21 Feb 2016 13:41:13 -0800 (PST) Received: from mail-wm0-f44.google.com (mail-wm0-f44.google.com [74.125.82.44]) by cuda.sgi.com with ESMTP id ME2xTqr8YGzhSrVJ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sun, 21 Feb 2016 13:41:05 -0800 (PST) Received: by mail-wm0-f44.google.com with SMTP id g62so133711544wme.0 for ; Sun, 21 Feb 2016 13:41:05 -0800 (PST) Subject: Re: richacl(7) man page review comments References: <56B770B6.7040803@gmail.com> <56B77262.7090107@gmail.com> <56C0F23C.7030902@gmail.com> From: "Michael Kerrisk (man-pages)" Message-ID: <56CA2EEB.9080504@gmail.com> Date: Sun, 21 Feb 2016 22:40:59 +0100 MIME-Version: 1.0 In-Reply-To: List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com To: Andreas Gruenbacher Cc: Andreas Dilger , linux-cifs@vger.kernel.org, Linux NFS Mailing List , Christoph Hellwig , Linux API , Trond Myklebust , lkml , XFS Developers , "J. Bruce Fields" , mtk.manpages@gmail.com, linux-fsdevel , Jeff Layton , linux-ext4 , Anna Schumaker SGVsbG8gQW5kcmVhcywKCk9uIDAyLzIwLzIwMTYgMDU6MzcgUE0sIEFuZHJlYXMgR3J1ZW5iYWNo ZXIgd3JvdGU6Cj4gSGkgTWljaGFlbCwKPiAKPiB0aGFua3MgYWdhaW4gZm9yIGFsbCB0aGUgZmVl ZGJhY2suIEkndmUgZm9sbG93ZWQgYWxsIHlvdXIgc3VnZ2VzdGlvbnM7Cj4gYWdhaW4sIHBsZWFz ZSBzZWUgdGhlIGdpdGh1YiByZXBvIGZvciB0aGUgbGF0ZXN0IHZlcnNpb246Cj4gCj4gICBodHRw czovL2dpdGh1Yi5jb20vYW5kcmVhcy1ncnVlbmJhY2hlci9yaWNoYWNsCgpJJ3ZlIG9uY2UgbW9y ZSBwdWxsZWQgZnJvbSB0aGUgbGF0ZXN0IGdpdDsgaGVyZSdzIHNvbWUgbW9yZSBjb21tZW50cy4K Cj4gLlwiCj4gLlwiIFJpY2hBQ0wgTWFudWFsIFBhZ2VzCj4gLlwiCj4gLlwiIENvcHlyaWdodCAo QykgMjAxNSwyMDE2ICBSZWQgSGF0LCBJbmMuCj4gLlwiIFdyaXR0ZW4gYnkgQW5kcmVhcyBHcnVl bmJhY2hlciA8YWdydWVuYmFAcmVkaGF0LmNvbT4KPiAuXCIgVGhpcyBpcyBmcmVlIGRvY3VtZW50 YXRpb247IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgo+IC5cIiBtb2RpZnkgaXQgdW5k ZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcwo+IC5cIiBw dWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24g MiBvZgo+IC5cIiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVy c2lvbi4KPiAuXCIKPiAuXCIgVGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlJ3MgcmVmZXJl bmNlcyB0byAib2JqZWN0IGNvZGUiCj4gLlwiIGFuZCAiZXhlY3V0YWJsZXMiIGFyZSB0byBiZSBp bnRlcnByZXRlZCBhcyB0aGUgb3V0cHV0IG9mIGFueQo+IC5cIiBkb2N1bWVudCBmb3JtYXR0aW5n IG9yIHR5cGVzZXR0aW5nIHN5c3RlbSwgaW5jbHVkaW5nCj4gLlwiIGludGVybWVkaWF0ZSBhbmQg cHJpbnRlZCBvdXRwdXQuCj4gLlwiCj4gLlwiIFRoaXMgbWFudWFsIGlzIGRpc3RyaWJ1dGVkIGlu IHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gLlwiIGJ1dCBXSVRIT1VUIEFOWSBX QVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gLlwiIE1FUkNI QU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUK PiAuXCIgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KPiAuXCIK PiAuXCIgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwg UHVibGljCj4gLlwiIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIG1hbnVhbC4gIElmIG5vdCwgc2Vl Cj4gLlwiIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KPiAuXCIKPiAuZGUgVVJMCj4g XFwkMiBcKGxhVVJMOiBcXCQxIFwocmFcXCQzCj4gLi4KPiAuaWYgXG5bLmddIC5tc28gd3d3LnRt YWMKPiAuVEggUklDSEFDTCA3IDIwMTUtMDktMDEgIkxpbnV4IiAiUmljaCBBY2Nlc3MgQ29udHJv bCBMaXN0cyIKPiAuU0ggTkFNRQo+IHJpY2hhY2wgXC0gUmljaCBBY2Nlc3MgQ29udHJvbCBMaXN0 cwo+IC5TSCBERVNDUklQVElPTgo+IFJpY2ggQWNjZXNzIENvbnRyb2wgTGlzdHMgKFJpY2hBQ0xz KSBhcmUgYW4gZXh0ZW5zaW9uIG9mIHRoZSBQT1NJWCBmaWxlCj4gcGVybWlzc2lvbiBtb2RlbCAo c2VlCj4gLkJSIGFjbCAoNSkpCj4gdG8gc3VwcG9ydAo+IC5VUkwgaHR0cHM6Ly90b29scy5pZXRm Lm9yZy9yZmMvcmZjNTY2MS50eHQgIk5GU3Y0IEFjY2VzcyBDb250cm9sIExpc3RzIgo+IG9uIGxv Y2FsIGFuZCByZW1vdGUtbW91bnRlZCBmaWxlc3lzdGVtcy4KPiAKPiBBIFJpY2hBQ0wgY2FuIGFs d2F5cyBiZSB0cmFuc2xhdGVkIGludG8gYW4gZXF1aXZhbGVudCBORlN2NCBBQ0wgd2hpY2ggZ3Jh bnRzCj4gdGhlIHNhbWUgcGVybWlzc2lvbnMuCj4gCj4gUmljaEFDTHMgY2FuIGJlIGVuYWJsZWQg b24gc3VwcG9ydGVkIGxvY2FsIGZpbGVzeXN0ZW1zIChjdXJyZW50bHksIGV4dDQgYW5kCj4gWEZT KS4gIFRoaXMgZGlzYWJsZXMgUE9TSVggQWNjZXNzIENvbnRyb2wgTGlzdHM7IHRoZSB0d28gQUNM IG1vZGVscyBjYW5ub3QKPiBjb2V4aXN0IG9uIHRoZSBzYW1lIGZpbGVzeXN0ZW0uCj4gCj4gVGhl IGluLWtlcm5lbCBORlN2NCBzZXJ2ZXIgYW5kIGNsaWVudCBhbHNvIGluY2x1ZGUgUmljaEFDTCBz dXBwb3J0LgoKUmV3cml0ZSB0aGUgcHJlY2VkaW5nIHR3byBwYXJhcyBpbiBhIGJldHRlciBsb2dp Y2FsIHNwbGl0IGFuZCBvcmRlcjoKCltbClJpY2hBQ0xzIGNhbiBiZSBlbmFibGVkIG9uIHN1cHBv cnRlZCBsb2NhbCBmaWxlc3lzdGVtcyAoY3VycmVudGx5LCBleHQ0IGFuZApYRlMpLiAgVGhlIGlu LWtlcm5lbCBORlN2NCBzZXJ2ZXIgYW5kIGNsaWVudCBhbHNvIGluY2x1ZGUgUmljaEFDTCBzdXBw b3J0LgoKRW5hYmxpbmcgUmljaEFDTHMgZGlzYWJsZXMgUE9TSVggQWNjZXNzIENvbnRyb2wgTGlz dHM7CnRoZSB0d28gQUNMIG1vZGVscyBjYW5ub3QgY29leGlzdCBvbiB0aGUgc2FtZSBmaWxlc3lz dGVtLgpdXQoKPiAKPiBXaGVuIHVzZWQgb24gYSBmaWxlc3lzdGVtIHRoYXQgZG9lcyBub3Qgc3Vw cG9ydCBSaWNoQUNMcywgdGhlCj4gLkJSIGdldHJpY2hhY2wgKDEpCj4gYW5kCj4gLkJSIHNldHJp Y2hhY2wgKDEpCj4gdXRpbGl0aWVzIHdpbGwgb3BlcmF0ZSBvbiB0aGUgZmlsZSBwZXJtaXNzaW9u IGJpdHMgaW5zdGVhZDoKPiAuQlIgZ2V0cmljaGFjbCAoMSkKPiB3aWxsIGRpc3BsYXkgdGhlIGZp bGUgcGVybWlzc2lvbiBiaXRzIGFzIGEgUmljaEFDTDsgd2hlbiBhIFJpY2hBQ0wKPiBpcyBzZXQg d2l0aAo+IC5CUiBzZXRyaWNoYWNsICgxKQo+IHdoaWNoIGNhbiBiZSByZXByZXNlbnRlZCBleGFj dGx5IGJ5IHRoZSBmaWxlIHBlcm1pc3Npb24gYml0cywKPiAuQlIgc2V0cmljaGFjbCAoMSkKPiB3 aWxsIHNldCB0aGUgZmlsZSBwZXJtaXNzaW9uIGJpdHMgaW5zdGVhZC4gIEFuIGF0dGVtcHQgdG8g c2V0IGEgUmljaEFDTCB0aGF0Cj4gY2Fubm90IGJlIHJlcHJlc2VudGVkIGV4YWN0bHkgYnkgdGhl IGZpbGUgcGVybWlzc2lvbiBiaXRzIHJlc3VsdHMgaW4gYW4gZXJyb3IuCj4gCj4gLlNTIFN0cnVj dHVyZSBvZiBSaWNoQUNMcwo+IAo+IFJpY2hBQ0xzIGNvbnNpc3Qgb2YgYSBudW1iZXIgb2YgQUNM IGVudHJpZXMsIHRocmVlIGZpbGUgbWFza3MsIGFuZCBzb21lIGZsYWdzCgpzL3NvbWUgZmxhZ3Mv YSBzZXQgb2YgZmxhZ3MvCgo+IHNwZWNpZnlpbmcgYXR0cmlidXRlcyBvZiB0aGUgQUNMIGFzIHdo b2xlIChieSBjb250cmFzdCB3aXRoIHRoZSBwZXItQUNMLWVudHJ5CgpzL3dob2xlL2Egd2hvbGUv Cgo+IGZsYWdzIGRlc2NyaWJlZCBiZWxvdykuCj4gCj4gRWFjaCBvZiB0aGUgQUNMIGVudHJpZXMg YWxsb3dzIG9yIGRlbmllcyBzb21lIHBlcm1pc3Npb25zIHRvIGEgcGFydGljdWxhciB1c2VyLAo+ IGdyb3VwLCBvciBzcGVjaWFsIGlkZW50aWZpZXIuIEFuIEFDTCBlbnRyeSBjb25zaXN0cyBvZiBm b3VyIGZpZWxkczoKPiAKPiAuSVAgXChidSA0CgpzLzQvMi8KCj4gQSB0YWcgd2hpY2ggc3BlY2lm aWVzIHRoZSB1c2VyLCBncm91cCwgb3Igc3BlY2lhbCBpZGVudGlmaWVyIHRoZSBlbnRyeSBhcHBs aWVzCj4gdG8uICBTcGVjaWFsIGlkZW50aWZpZXJzIGNhbiBiZSB0aGUgZmlsZSBvd25lciwgdGhl IG93bmluZyBncm91cCwgb3IgZXZlcnlvbmUuCgo9PT4KU3BlY2lhbCBpZGVudGlmaWVycyBjb3Jy ZXNwb25kIHRvIG9uZSBvZiB0aHJlZSBmaWxlIG1hc2tzIGZvciB0aGUgZmlsZSBvd25lcgouUkIg KCBvd25lckAgKSwKdGhlIG93bmluZyBncm91cAouUkIgKCBncm91cEAgKSwKb3IgZXZlcnlvbmUK LlJCICggZXZlcnlvbmVAICkuCgo+IC5JUCBcKGJ1Cj4gQSBzZXQgb2YgcGVybWlzc2lvbnMgdGhl IGVudHJ5IGFsbG93cyBvciBkZW5pZXMuCj4gLklQIFwoYnUKPiBBIHNldCBvZiBmbGFncyB0aGF0 IGluZGljYXRlIHdoZXRoZXIgdGhlIHVzZXIgb3IgZ3JvdXAgaWRlbnRpZmllciBpcyBtYXBwZWQg b3IKPiB1bm1hcHBlZCwgYW5kIHdoZXRoZXIgdGhlIGVudHJ5IGhhcyBiZWVuIGFuZCBjYW4gYmUg aW5oZXJpdGVkLgo+IC5JUCBcKGJ1IDQKCnMvIDQvLwoKPiBBIHR5cGUgZmllbGQgaW5kaWNhdGlu ZyB3aGV0aGVyIHRoZSBlbnRyeSBhbGxvd3Mgb3IgZGVuaWVzIGFjY2Vzcy4KCnMvYWNjZXNzL3Ro ZSBwZXJtaXNzaW9ucyBzcGVjaWZpZWQgaW4gdGhlIHNlY29uZCBmaWVsZC8KCj4gLlBQCj4gVGhl IG93bmVyLCBncm91cCwgYW5kIG90aGVyIGZpbGUgbWFza3MgZnVydGhlciBjb250cm9sIHdoaWNo IHBlcm1pc3Npb25zIHRoZQo+IEFDTCBncmFudHMsIHN1YmplY3QgdG8gdGhlCj4gLkJSIG1hc2tl ZCAiXCAoIiBtICkKPiBhbmQKPiAuQlIgd3JpdGVfdGhyb3VnaCAiXCAoIiB3ICkKPiBBQ0wgZmxh Z3M6IHdoZW4gdGhlIHBlcm1pc3Npb25zIG9mIGEgZmlsZSBvciBkaXJlY3RvcnkgYXJlIGNoYW5n ZWQgd2l0aAo+IC5CUiBjaG1vZCAoMiksCj4gdGhlIGZpbGUgbWFza3MgYXJlIHNldCBiYXNlZCBv biB0aGUgbmV3IGZpbGUgbW9kZSwgYW5kIHRoZQo+IC5CIG1hc2tlZAo+IGFuZAo+IC5CIHdyaXRl X3Rocm91Z2gKPiBBQ0wgZmxhZ3MgYXJlIHNldC4gTGlrZXdpc2UsIHdoZW4gYSBuZXcgZmlsZSBv ciBkaXJlY3RvcnkgaW5oZXJpdHMgYW4gQUNMIGZyb20KPiBpdHMgcGFyZW50IGRpcmVjdG9yeSwg dGhlIGZpbGUgbWFza3MgYXJlIHNldCB0byB0aGUgaW50ZXJzZWN0aW9uIGJldHdlZW4gdGhlCj4g cGVybWlzc2lvbnMgZ3JhbnRlZCBieSB0aGUgaW5oZXJpdGVkIEFDTCBhbmQgdGhlCj4gLkkgbW9k ZQo+IHBhcmFtZXRlciBhcyBnaXZlbiB0bwo+IC5CUiBvcGVuICIoMiksICIgbWtkaXIgKDIpLAo+ IGFuZCBzaW1pbGFyLCBhbmQgdGhlCj4gLkIgbWFza2VkCj4gQUNMIGZsYWcgaXMgc2V0LiBJbiBi b3RoIGNhc2VzLCB0aGUgZmlsZSBtYXNrcyBsaW1pdCB0aGUgcGVybWlzc2lvbnMgdGhhdCB0aGUK PiBBQ0wgd2lsbCBncmFudC4KPiAKPiBUaGUgYWR2YW50YWdlIG9mIHRoaXMgYXBwcm9hY2ggb3Zl ciBkaXJlY3RseSBtb2RpZnlpbmcgdGhlIEFDTCBlbnRyaWVzIGlzIHRoYXQKPiBwZXJtaXNzaW9u cyBkZWZpbmVkIGluIEFDTCBlbnRyaWVzIGFyZSBub3QgbG90IHdoZW4gdGhlIGZpbGUgbWFza3Mg YXJlIGxhdGVyCgpzL2xvdC9sb3N0LwoKPiBzZXQgdG8gYmUgbGVzcyByZXN0cmljdGl2ZS4KCihJ IHRoaW5rKSBJIGtub3cgd2hhdCB5b3UgYXJlIHRyeWluZyB0byBzYXkgaW4gdGhlIHByZXZpb3Vz IHBhcmFncmFwaCwKYnV0ICJ0aGlzIGFwcHJvYWNoIiBhbmQgImRpcmVjdGx5IG1vZGlmeWluZyB0 aGUgQUNMIGVudHJpZXMiIGlzIGEgbGl0dGxlCnZhZ3VlLiAgTWFza3MgYXJlIGFib3V0IHNvbHZp bmcgdGhlIGh5c3RlcmVzaXMgcHJvYmxlbSwgcmlnaHQ/IFNvLCBob3cKYWJvdXQgc29tZSB0ZXh0 IGFsb25nIHRoZSBmb2xsb3dpbmcgbGluZXMgKEknbSBzdXJlIHlvdSBjYW4gaW1wcm92ZSk6Cgpb WwpUaGUgcHVycG9zZSBvZiB0aGUgZmlsZSBtYXNrcyBpcyB0byBhbGxvdyBhcHBsaWNhdGlvbnMg dGhhdCBhcmUgdW5hd2FyZQpvZiBSaWNoQUNMcyB0byBwbGFjZSBsaW1pdHMgb24gdGhlIHBlcm1p c3Npb25zIGdyYW50ZWQgYnkgdmFyaW91cwpjbGFzc2VzIG9mIFJpY2hBQ0wgaW4gYSBtYW5uZXIg dGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdHJhZGl0aW9uYWwKdXNlci9ncm91cC9vdGhlciBzZW1h bnRpY3MsIHdpdGhvdXQgbW9kaWZ5aW5nIHRoZSBBQ0wgZW50cmllcyBpbiB0aG9zZQpjbGFzc2Vz LiAgV2l0aG91dCB0aGUgZmlsZSBtYXNrcywgdGhlIG9ubHkgYWx0ZXJuYXRpdmUgd291bGQgYmUg Zm9yIHRoZQprZXJuZWwgdG8gZGlyZWN0bHkgbW9kaWZ5IHRoZSBBQ0wgZW50cmllcyBpbiB0aG9z ZSBjbGFzc2VzLiBIb3dldmVyLAp0aGlzIGxhdHRlciBhcHByb2FjaCBjb3VsZCBoYXZlIGEgImh5 c3RlcmVzaXMgZWZmZWN0Iiwgd2hlcmVieQphIFJpY2hBQ0wtdW5hd2FyZSBhcHBsaWNhdGlvbiB0 aGF0IHBlcmZvcm1zIGEgdHJhbnNpdGlvbiBmcm9tIG9uZSBmaWxlCm1vZGUgdG8gYW5vdGhlciBm aWxlIG1vZGUgYW5kIHRoZW4gYmFjayB0byB0aGUgb3JpZ2luYWwgZmlsZSBtb2RlCmNvdWxkIGNh dXNlIGRlc3RydWN0aW9uIG9mIHRoZSBwZXJtaXNzaW9uIGluZm9ybWF0aW9uIGluIEFDTCBlbnRy aWVzLgpdXQoKPiAKPiBOb3RlIHRoYXQgZW50cmllcyB3aXRoIHRoZSBpZGVudGlmaWVyCj4gLkIg ZXZlcnlvbmVACj4gYXBwbHkgdG8gYWxsIHByb2Nlc3Nlcywgd2hlcmVhcyB0aGUgXChscW90aGVy XChycSBmaWxlIHBlcm1pc3Npb25zIGFuZAo+IFwobHFvdGhlclwocnEgZW50cmllcyBpbiBQT1NJ WCBBQ0xzIGFwcGx5IHRvIGFsbCBwcm9jZXNzZXMgd2hpY2ggYXJlIG5vdCB0aGUKCkknZCBiZSBp bmNsaW5lZCB0byB1c2UgKG9yIGFkZCkgXGZCQUNMX09USEVSXGZQIGluc3RlYWQgb2YgIm90aGVy IgppbiB0aGUgcHJlY2VkaW5nIGxpbmUuICBUaGluZ3MgbWFrZXMgdGhpbmdzIElNTyBhIGxpdHRs ZSBjbGVhcmVyIHdoZW4KeW91IHRyeSB0byBkaXN0aW5ndWlzaCBmcm9tICJvdGhlciIgZmlsZSBw ZXJtaXNzaW9ucy4KCj4gb3duZXIsIGFyZSBub3QgaW4gdGhlIG93bmluZyBncm91cCwgYW5kIGRv IG5vdCBtYXRjaCBhIHVzZXIgb3IgZ3JvdXAgbWVudGlvbmVkCj4gaW4gdGhlIEFDTC4KPiAKPiBV bmxpa2UgUE9TSVggQUNMcywgUmljaEFDTHMgZG8gbm90IGhhdmUgc2VwYXJhdGUgXChscWFjY2Vz c1wocnEgQUNMcyB0aGF0Cj4gZGVmaW5lIHRoZSBhY2Nlc3MgcGVybWlzc2lvbnMgYW5kIFwobHFk ZWZhdWx0XChycSBBQ0xzIHRoYXQgZGVmaW5lIHRoZQo+IGluaGVyaXRhYmxlIHBlcm1pc3Npb25z LiAgSW5zdGVhZCwgZmxhZ3Mgb24gZWFjaCBBQ0wgZW50cnkgZGV0ZXJtaW5lIHdoZXRoZXIKPiB0 aGUgZW50cnkgaXMgZWZmZWN0aXZlIGR1cmluZyBhY2Nlc3MgY2hlY2tzIGFuZC9vciBpbmhlcml0 YWJsZS4KPiAKPiAKPiAuU1MgQUNMIGZsYWdzCj4gCj4gVGhlIGZvbGxvd2luZyBmbGFncyBvbiBB Q0xzIGFyZSBkZWZpbmVkOgoKcy9mbGFncyBvbiBBQ0xzL0FDTCBmbGFncy8KCj4gCj4gLlRQCj4g LkJSIG1hc2tlZCAiXCAoIiBtICkKPiBXaGVuIHNldCwgdGhlIGZpbGUgbWFza3MgZGVmaW5lIHVw cGVyIGxpbWl0cyBvbiB0aGUgcGVybWlzc2lvbnMgdGhlIEFDTCBtYXkKPiBncmFudC4gIFdoZW4g bm90IHNldCwgdGhlIGZpbGUgbWFza3MgYXJlIGlnbm9yZWQuCj4gLlRQCj4gLkJSIHdyaXRlX3Ro cm91Z2ggIlwgKCIgdyApCj4gV2hlbiB0aGlzIGZsYWcgYW5kIHRoZQo+IC5CIG1hc2tlZAo+IGZs YWcgYXJlIGJvdGggc2V0LCB0aGUgb3duZXIgYW5kIG90aGVyIGZpbGUgbWFza3MgZGVmaW5lIHRo ZSBhY3R1YWwgcGVybWlzc2lvbnMKPiBncmFudGVkIHRvIHRoZSBmaWxlIG93bmVyIGFuZCB0byBv dGhlcnMgaW5zdGVhZCBvZiBkZWZpbmluZyBhbiB1cHBlciBsaW1pdC4KPiBXaGVuIHRoZQo+IC5C IG1hc2tlZAo+IGZsYWcgaXMgbm90IHNldCwgdGhlIHdyaXRlX3Rocm91Z2ggZmxhZyBoYXMgbm8g ZWZmZWN0LgoKVXNlIC5CUiB3cml0ZV90aHJvdWdoIGZvciBwcmVjZWRpbmcgbGluZQoKPiAuVFAK PiAuQlIgYXV0b19pbmhlcml0ICJcICgiIGEgKQo+IEF1dG9tYXRpYyBJbmhlcml0YW5jZSBpcyBl bmFibGVkLiAgU2VlCj4gLklSICJBdXRvbWF0aWMgSW5oZXJpdGFuY2UiIC4KPiAuVFAKPiAuQlIg cHJvdGVjdGVkICJcICgiIHAgKQo+IFRoZSBBQ0wgaXMgcHJvdGVjdGVkIGZyb20gbW9kaWZpY2F0 aW9uIGJ5IEF1dG9tYXRpYwo+IEluaGVyaXRhbmNlLgo+IC5UUAo+IC5CUiBkZWZhdWx0ZWQgIlwg KCIgZCApCj4gSW5kaWNhdGVzIHRoYXQgdGhlIEFDTCBoYXMgYmVlbiBhc3NpZ25lZCBpbiBhbiBh cHBsaWNhdGlvbi1kZXBlbmRlbnQgd2F5IHdoZW4KPiB0aGUgZmlsZSBvciBkaXJlY3Rvcnkgd2Fz IGNyZWF0ZWQ7IGl0IGhhcyBuZWl0aGVyIGJlZW4gaW5oZXJpdGVkIG5vciBzZXQKPiBleHBsaWNp dGx5LiBBQ0xzIG9mIGZpbGVzIGNyZWF0ZWQgb24gTGludXggd2lsbCBuZXZlciBoYXZlIHRoZQo+ IC5CIGRlZmF1bHRlZAo+IGZsYWcgc2V0LiAKClRoZSBwcmVjZWRpbmcgc2VudGVuY2UgaW1tZWRp YXRlbHkgdHJpZ2dlcnMgYW4gb2J2aW91cyBxdWVzdGlvbiBmb3IgdGhlCnJlYWRlci4gIFNvLCBk byB3ZSBuZWVkIGEgc2VudGVuY2UgaGVyZSB0byBzYXkgd2hlbi93aGVyZSB0aGUgImRlZmF1bHRl ZCIKZmxhZyBpcyBzZXQ/Cj4gICAgICAgICAgIFdoZW4gdGhpcyBmbGFnIGlzIHNldCBmb3IgYW4g QUNMLCBBdXRvbWF0aWMgSW5oZXJpdGFuY2Ugd2lsbAo+IGNvbXBsZXRlbHkgcmVwbGFjZSB0aGUg QUNMLgo+IAo+IC5TUyBBQ0wgZW50cnkgZmxhZ3MKPiAKPiBUaGUgZm9sbG93aW5nIGZsYWdzIG9u IEFDTCBlbnRyaWVzIGFyZSBkZWZpbmVkOgo+IAo+IC5UUAo+IC5CUiBmaWxlX2luaGVyaXQgIlwg KCIgZiApCj4gV2hlbiB0aGlzIGZsYWcgYXBwZWFycyBpbiB0aGUgQUNMIGVudHJ5IG9mIGEgZGly ZWN0b3J5LCB0aGVuOgo+IC5SUwo+IC5JUCBcKGJ1IDQKPiBUaGF0IGVudHJ5IGlzIGluaGVyaXRl ZCBieSBuZXcgZmlsZXMgY3JlYXRlZCBpbiB0aGUgZGlyZWN0b3J5IHN1Y2ggdGhhdCB0aGUKCnMv NC8yLwoKPiBwZXJtaXNzaW9ucyBvZiB0aGUgZW50cnkgYXBwbHkgdG8gdGhlIGZpbGUgKHRoZSBp bmhlcml0YW5jZSBmbGFncyBvZiB0aGUKPiBpbmhlcml0ZWQgZW50cnkgYXJlIGNsZWFyZWQpLgo+ IC5JUCBcKGJ1IDQKPiBUaGUgZW50cnkgaXMgaXMgaW5oZXJpdGVkIGJ5IG5ldyBzdWJkaXJlY3Rv cmllcyBjcmVhdGVkIGluIHRoZSBkaXJlY3Rvcnkgc3VjaAoKcy8gNC8vCgo+IHRoYXQgdGhlIHBl cm1pc3Npb25zIG9mIHRoZSBlbnRyeSB3aWxsIGFwcGx5IHRvIG5ldyBmaWxlcyBjcmVhdGVkIGlu IHRoZQo+IHN1YmRpcmVjdG9yeS4KPiAuUkUKPiAuVFAKPiAuQlIgZGlyX2luaGVyaXQgIlwgKCIg ZCApCj4gV2hlbiB0aGlzIGZsYWcgYXBwZWFycyBpbiB0aGUgQUNMIGVudHJ5IG9mIGEgZGlyZWN0 b3J5LCB0aGVuIHRoYXQgZW50cnkgaXMKPiBpbmhlcml0ZWQgYnkgbmV3IHN1YmRpcmVjdG9yaWVz IGNyZWF0ZWQgaW4gdGhlIGRpcmVjdG9yeSBzdWNoIHRoYXQgdGhlCj4gcGVybWlzc2lvbnMgb2Yg dGhlIGVudHJ5IGFwcGx5IHRvIHRoZSBzdWJkaXJlY3RvcnkgKHRoZQo+IC5CIGluaGVyaXRfb25s eQo+IGZsYWcgaXMgY2xlYXJlZCkuCj4gLlRQCj4gLkJSIG5vX3Byb3BhZ2F0ZSAiXCAoIiBuICkK PiBJbmhlcml0YW5jZSBzdG9wcyBhdCB0aGUgbmV4dCBzdWJkaXJlY3RvcnkgbGV2ZWwuICBXaGVu IGEgZmlsZSBvciBkaXJlY3RvcnkKPiBpbmhlcml0cyBhbiBlbnRyeSB0aGF0IGhhcyB0aGlzIGZs YWcgc2V0LCB0aGUKPiAuQlIgZmlsZV9pbmhlcml0ICIsICIgZGlyX2luaGVyaXQgIiwgIiBub19w cm9wYWdhdGUgIiwgYW5kICIgaW5oZXJpdF9vbmx5Cj4gZmxhZ3MgYXJlIGNsZWFyZWQuCj4gLlRQ Cj4gLkJSIGluaGVyaXRfb25seSAiXCAoIiBpICkKPiBUaGUgZW50cnkgZGVmaW5lcyBpbmhlcml0 YWJsZSBwZXJtaXNzaW9ucyBvbmx5IGFuZCBpcyBpZ25vcmVkIGZvciBhY2Nlc3MKPiBjaGVja2lu Zy4gIFdoZW4gYSBmaWxlIG9yIGRpcmVjdG9yeSBpbmhlcml0cyBhbiBlbnRyeSB0aGF0IGhhcyB0 aGlzIGZsYWcgc2V0LAo+IHRoZSBmbGFnIGlzIGNsZWFyZWQuCj4gLlRQCj4gLkJSIGluaGVyaXRl ZCAiXCAoIiBhICkKPiBUaGUgZW50cnkgaGFzIGJlZW4gYXV0b21hdGljYWxseSBpbmhlcml0ZWQg ZnJvbSB0aGUgcGFyZW50IGRpcmVjdG9yeTsgdGhlCj4gQUNMJ3MKPiAuQiBhdXRvX2luaGVyaXQK PiBmbGFnIHNob3VsZCBiZSBvbi4KCldoeSAic2hvdWxkIGJlIiBpbiB0aGUgcHJldmlvdXMgc2Vu dGVuY2U/IEkgdGhpbmsgYSBsaXR0bGUgZXhwbGFuYXRpb24KaXMgbmVlZGVkIGhlcmUuLi4KPiAu VFAKPiAuQlIgdW5tYXBwZWQgIlwgKCIgdSApCj4gVGhlIHVzZXIgb3IgZ3JvdXAgaWRlbnRpZmll ciBpcyBhIHRleHR1YWwgc3RyaW5nIGFuZCBpcyBub3QgbWFwcGVkIHRvIGEgbnVtZXJpYwo+IHVz ZXIgb3IgZ3JvdXAgaWRlbnRpZmllci4gIEFDTHMgd2l0aCB1bm1hcHBlZCBpZGVudGlmaWVycyBj YW4gb2NjdXIgb24gTkZTdjQKPiBtb3VudGVkIGZpbGVzeXN0ZW1zIHdoZW4gdGhlIGNsaWVudCBj YW5ub3QgZGV0ZXJtaW5lIG51bWVyaWMgdXNlciBvciBncm91cAo+IGlkZW50aWZpZXJzIGZvciBz b21lIG9mIHRoZSBORlN2NCB1c2VyQGRvbWFpbiBvciBncm91cEBkb21haW4gd2hvIHZhbHVlcy4g IFRoZXkKPiBjYW5ub3QgYmUgYXNzaWduZWQgdG8gbG9jYWwgZmlsZXMgb3IgZGlyZWN0b3JpZXMu Cj4gCj4gLlNTIFBlcm1pc3Npb25zCj4gCj4gVGhlIGZvbGxvd2luZyBwZXJtaXNzaW9ucyBhcmUg ZGVmaW5lZCBmb3IgUmljaEFDTCBlbnRyaWVzIGFuZCBmb3IgdGhlIHRocmVlCj4gZmlsZSBtYXNr czoKPiAKPiAuVFAKPiAuQlIgcmVhZF9kYXRhICIgLyAiIGxpc3RfZGlyZWN0b3J5ICJcICgiIHIg KQo+IEZvciBhIGZpbGU6IHJlYWQgdGhlIGRhdGEgb2YgdGhlIGZpbGUuCj4gRm9yIGEgZGlyZWN0 b3J5OiBsaXN0IHRoZSBjb250ZW50cyBvZiB0aGUgZGlyZWN0b3J5Lgo+IC5UUAo+IC5CUiB3cml0 ZV9kYXRhICIgLyAiIGFkZF9maWxlICJcICgiIHcgKQo+IEZvciBhIGZpbGU6IG1vZGlmeSB0aGUg ZGF0YSBvZiB0aGUgZmlsZTsgZG9lcyBub3QgaW5jbHVkZSBvcGVuaW5nIHRoZSBmaWxlIGluCj4g YXBwZW5kIG1vZGUuCj4gRm9yIGEgZGlyZWN0b3J5OiBhZGQgYSBuZXcgZmlsZSBpbiB0aGUgZGly ZWN0b3J5Lgo+IC5UUAo+IC5CUiBhcHBlbmRfZGF0YSAiIC8gIiBhZGRfc3ViZGlyZWN0b3J5ICJc ICgiIHAgKQo+IEZvciBhIGZpbGU6IG9wZW4gdGhlIGZpbGUgaW4gYXBwZW5kIG1vZGUuCj4gRm9y IGEgZGlyZWN0b3J5OiBjcmVhdGUgYSBzdWJkaXJlY3RvcnkgaW4gdGhlIGRpcmVjdG9yeS4KPiAu VFAKPiAuQlIgZXhlY3V0ZSAiXCAoIiB4ICkKPiBGb3IgYSBmaWxlOiBleGVjdXRlIHRoZSBmaWxl Lgo+IEZvciBhIGRpcmVjdG9yeTogdHJhdmVyc2UgLyBzZWFyY2ggdGhlIGRpcmVjdG9yeS4KCnMl dHJhdmVyc2UgLyBzZWFyY2gldHJhdmVyc2UgKHNlYXJjaCklCj4gLlRQCj4gLkJSIGRlbGV0ZV9j aGlsZCAiXCAoIiBkICkKPiBEZWxldGUgYSBmaWxlIG9yIGRpcmVjdG9yeSB3aXRoaW4gYSBkaXJl Y3RvcnkuICBUaGlzIHBlcm1pc3Npb24gaXMgbWVhbmluZ2xlc3MKPiBmb3Igbm9uLWRpcmVjdG9y aWVzLgoKPT0+ICJUaGlzIHBlcm1pc3Npb24gaXMgbWVhbnVuZ2Z1bCBvbmx5IGZvciBkaXJlY3Rv cmllcy4iCgo+IC5UUAo+IC5CUiBkZWxldGUgIlwgKCIgRCApCj4gRGVsZXRlIHRoZSBmaWxlIG9y IGRpcmVjdG9yeS4KPiAuVFAKPiAuQlIgcmVhZF9hdHRyaWJ1dGVzICJcICgiIGEgKQo+IFJlYWQg YmFzaWMgYXR0cmlidXRlcyBvZiBhIGZpbGUgb3IgZGlyZWN0b3J5IChzZWUKPiAuQlIgc3RhdCAo MikpLgo+IFRoaXMgcGVybWlzc2lvbiBpcyBkZWZpbmVkIGJ5IE5GU3Y0LiAgSXQgaXMgc3RvcmVk LCBidXQgaWdub3JlZC4gIFJlYWRpbmcgYmFzaWMKPiBhdHRyaWJ1dGVzIG9mIGZpbGVzIGFuZCBk aXJlY3RvcmllcyBpcyBhbHdheXMgYWxsb3dlZCBvbiBMaW51eC4KPiAuVFAKPiAuQlIgd3JpdGVf YXR0cmlidXRlcyAiXCAoIiBBICkKPiBDaGFuZ2UgdGhlIHRpbWVzIGFzc29jaWF0ZWQgd2l0aCBh IGZpbGUgb3IgZGlyZWN0b3J5IHRvIGFuIGFyYml0cmFyeSB2YWx1ZS4KPiBUaGlzIHBlcm1pc3Np b24gaXMgYWx3YXlzIGltcGxpY2l0bHkgZ3JhbnRlZCB0byB0aGUgZmlsZSBvd25lci4KPiAuVFAK PiAuQlIgcmVhZF9hY2wgIlwgKCIgYyApCj4gUmVhZCB0aGUgQUNMIG9mIGEgZmlsZSBvciBkaXJl Y3RvcnkuIFRoaXMgcGVybWlzc2lvbiBpcyBhbHdheXMKPiBpbXBsaWNpdGx5IGdyYW50ZWQuCgpT bywgSSB0aGluayBhIHNlbnRlbmNlIGV4cGxhaW5pbmcgd2h5ICJyZWFkX2FjbCIgZXhpc3RzIHdv dWxkIGJlCmhlbHBmdWwsIHNpbmNlIHRoZSByZWFkZXIgaXMgbGVmdCBhIGxpdHRsZSBwdXp6bGVk IGFib3V0IGl0cyBwdXJwb3NlIGlmCml0IGlzIGFsd2F5cyBpbXBsaWNpdGx5IGdyYW50ZWQuCgo+ IC5UUAo+IC5CUiB3cml0ZV9hY2wgIlwgKCIgQyApCj4gQ2hhbmdlIHRoZSBBQ0wgb3IgZmlsZSBt b2RlIG9mIGEgZmlsZSBvciBkaXJlY3RvcnkuCj4gLlRQCj4gLkJSIHdyaXRlX293bmVyICJcICgi IG8gKQo+IFRha2Ugb3duZXJzaGlwIG9mIGEgZmlsZSBvciBkaXJlY3RvcnkuICBDaGFuZ2UgdGhl IG93bmluZyBncm91cCBvZiBhIGZpbGUgb3IKPiBkaXJlY3RvcnkgdG8gYSBncm91cCBvZiB3aGlj aCB0aGUgY2FsbGluZyBwcm9jZXNzIGlzIGEgbWVtYmVyLgo+IC5UUAoKRm9ybWF0dGluZyB0d2Vh azogYWRkICIuYWQgbCIgYmVmb3JlIHRoZSBmb2xsb3dpbmcgbGluZSBhbWQgIi5hZCIgYWZ0ZXIK dGhlIGxpbmUuCgo+IC5CUiByZWFkX25hbWVkX2F0dHJzICJcICgiIFIgIiksICIgd3JpdGVfbmFt ZWRfYXR0cnMgIlwgKCIgVyAiKSwgIiBzeW5jaHJvbml6ZSAiXCAoIiBTICIpLCAiIHdyaXRlX3Jl dGVudGlvbiAiXCAoIiBlICIpLCAiIHdyaXRlX3JldGVudGlvbl9ob2xkICJcICgiIEUgKQo+IFRo ZXNlIHBlcm1pc3Npb25zIGFyZSBkZWZpbmVkIGJ5IE5GU3Y0IC8gTkZTdjQuMS4gIFRoZXkgYXJl IHN0b3JlZCwgYnV0IGlnbm9yZWQuCgpzJS8lYW5kJQoKPiAuUFAKPiBGb3IgdGhlCj4gLkJSIHIg IiwgIiB3ICIsIGFuZCAiIHAKPiBwZXJtaXNzaW9ucyB3aGljaCBoYXZlIGRpZmZlcmVudCBsb25n IGZvcm1zIGZvciBmaWxlcyBhbmQgZGlyZWN0b3JpZXMsIHRoZQoKcy9wZXJtaXNzaW9ucy9wZXJt aXNzaW9ucywvCgo+IC5CUiBnZXRyaWNoYWNsICgxKQo+IHV0aWxpdHkgd2lsbCBvdXRwdXQgdGhl IGFwcHJvcHJpYXRlIGZvcm0ocykgZGVwZW5kaW5nIG9uIHRoZSBjb250ZXh0Lgo+IFRoZQo+IC5C UiBzZXRyaWNoYWNsICgxKQo+IHV0aWxpdHkgd2lsbCBhY2NlcHQgZWl0aGVyIGZvcm0gZm9yIGFu eSBmaWxlIHR5cGUuCj4gCj4gLlNTIFRleHQgZm9ybQo+IFRoZSBjb21tb24gdGV4dHVhbCByZXBy ZXNlbnRhdGlvbiBvZiBhIFJpY2hBQ0wgY29uc2lzdHMgb2YgdGhlIGNvbG9uLXNlcGFyYXRlZAo+ IGZpZWxkcyBvZiB0aGUgQUNMIGZsYWdzLCBmaWxlIG1hc2tzLCBhbmQgQUNMIGVudHJpZXMgaW4g dGhlIGZvbGxvd2luZwo+IGZvcm1hdDoKPiAuVFAKPiBcZkJmbGFnczpcZlJcZklhY2xfZmxhZ3Nc ZlIKPiBUaGUgQUNMIGZsYWdzLgo+IC5UUAo+IFxmQm93bmVyOlxmUlxmSXBlcm1cZlJcZkI6Om1h c2tcZlIsIFxmQmdyb3VwOlxmUlxmSXBlcm1cZlJcZkI6Om1hc2tcZlIsIFxmQm90aGVyOlxmUlxm SXBlcm1cZlJcZkI6Om1hc2tcZlIKPiBUaGUgZmlsZSBtYXNrcyBhbmQgdGhlaXIgcGVybWlzc2lv bnMuCj4gLlRQCj4gXGZJd2hvXGZSXGZCOlxmUlxmSXBlcm1cZlJcZkI6XGZSXGZJZmxhZ3NcZlJc ZkI6YWxsb3dcZlIsIFxmSXdob1xmUlxmQjpcZlJcZklwZXJtXGZSXGZCOlxmUlxmSWZsYWdzXGZS XGZCOmRlbnlcZlIKPiBGb3IgZWFjaCBBQ0wgZW50cnksIHdobyB0aGUgZW50cnkgYXBwbGllcyB0 bywgdGhlIHBlcm1pc3Npb25zIG9mIHRoZSBlbnRyeSwgdGhlCj4gZW50cnkgZmxhZ3MsIGFuZCB0 aGUgZW50cnkgdHlwZS4gVGhlIHdobyBmaWVsZCBpcyBvbmUgb2YgdGhlIGZvbGxvd2luZzoKCnMv d2hvL1xcZkl3aG9cXGZQLwoKPiAuUlMKPiAuSVAgXChidSA0CgpzLzQvMi8KCj4gT25lIG9mIHRo ZSBzcGVjaWFsIGlkZW50aWZpZXJzOgo+IC5CUiBvd25lckAgIiwgIiBncm91cEAgIiwgb3IgIiBl dmVyeW9uZUAgLAo+IC5JUCBcKGJ1Cj4gQQo+IC5CUiB1c2VyOiAiIG9yICIgdToKPiBwcmVmaXgg Zm9sbG93ZWQgYnkgYSB1c2VyIG5hbWUgb3IgdXNlciBJRCB0aGF0IGRlc2lnbmF0ZXMgYSBzcGVj aWZpYyB1c2VyLAo+IC5JUCBcKGJ1Cj4gQQo+IC5CUiBncm91cDogIiBvciAiIGc6Cj4gcHJlZml4 IGZvbGxvd2VkIGJ5IGEgZ3JvdXAgbmFtZSBvciBncm91cCBJRCB0aGF0IGRlc2lnbmF0ZXMgYSBz cGVjaWZpYyBncm91cC4KPiAuUkUKPiAuUFAKPiBUaGUgZW50cmllcyBhcmUgY29tbWEsIHdoaXRl c3BhY2UsIG9yIG5ld2xpbmUgc2VwYXJhdGVkLgo+IAo+IEZsYWdzIGFuZCBwZXJtaXNzaW9ucyBo YXZlIHNpbmdsZS1sZXR0ZXIgYXMgd2VsbCBhcyBsb25nIGZvcm1zLCBhcyBsaXN0ZWQgdW5kZXIK PiAuSVIgIkFDTCBmbGFncyIgLAo+IC5JUiAiQUNMIGVudHJ5IGZsYWdzIiAsCj4gYW5kCj4gLklS IFBlcm1pc3Npb25zIC4KPiBXaGVuIHRoZSBzaW5nbGUtbGV0dGVyIGZvcm1zIGFyZSB1c2VkLCB0 aGUgZmxhZ3Mgb3IgcGVybWlzc2lvbnMgYXJlCj4gY29uY2F0ZW5hdGVkLiBXaGVuIHRoZSBsb25n IGZvcm1zIGFyZSB1c2VkLCB0aGUgZmxhZ3Mgb3IgcGVybWlzc2lvbnMgYXJlCj4gc2VwYXJhdGVk IGJ5IHNsYXNoZXMuICBUbyBhbGlnbiBwZXJtaXNzaW9ucyBvciBmbGFncyB2ZXJ0aWNhbGx5LCBk YXNoZXMgY2FuIGJlCj4gdXNlZCBmb3IgcGFkZGluZy4KPiAKPiAuU1MgU2V0dGluZyBhbmQgbW9k aWZ5aW5nIGZpbGUgcGVybWlzc2lvbnMKPiBUaGUgYWNjZXNzIHBlcm1pc3Npb25zIGZvciBhIGZp bGUgY2FuIGVpdGhlciBiZSBzZXQgYnkgYXNzaWduaW5nIGFuIEFjY2Vzcwo+IENvbnRyb2wgTGlz dAo+IC5SQiAoIHNldHJpY2hhY2wgKDEpKQo+IG9yIGJ5IGNoYW5naW5nIHRoZSBmaWxlIG1vZGUg cGVybWlzc2lvbiBiaXRzCj4gLlJCICggY2htb2QgKDEpKS4KPiBJbiBhZGRpdGlvbiwgYSBmaWxl IGNhbiBpbmhlcml0IGFuIEFDTCBmcm9tIGl0cyBwYXJlbnQgZGlyZWN0b3J5IGF0IGNyZWF0aW9u Cj4gdGltZSBhcyBkZXNjcmliZWQgdW5kZXIKPiAuSVIgIlBlcm1pc3Npb25zIGF0IGZpbGUtY3Jl YXRpb24gdGltZSIgLgo+IAo+IC5TUyBBc3NpZ25pbmcgYW4gQWNjZXNzIENvbnRyb2wgTGlzdAo+ IFdoZW4gYXNzaWduaW5nIGFuIEFDTCB0byBhIGZpbGUsIHVubGVzcyBleHBsaWNpdGx5IHNwZWNp ZmllZCwgdGhlIG93bmVyLCBncm91cCwKPiBhbmQgb3RoZXIgZmlsZSBtYXNrcyB3aWxsIGJlIGNv bXB1dGVkIGZyb20gdGhlIEFDTCBlbnRyaWVzIGFzIGRlc2NyaWJlZCBpbgo+IHRoZSBzZWN0aW9u Cj4gLklSICJDb21wdXRpbmcgdGhlIG1heGltdW0gZmlsZSBtYXNrcyIgLgo+IFRoZSBvd25lciwg Z3JvdXAsIGFuZCBvdGhlciBmaWxlIG1vZGUgcGVybWlzc2lvbiBiaXRzIGFyZSB0aGVuIGVhY2gg c2V0IGZyb20KPiB0aGUgb3duZXIsIGdyb3VwLCBhbmQgb3RoZXIgZmlsZSBtYXNrIGFzIGZvbGxv d3M6Cj4gLklQIFwoYnUgNAoKcy80LzIvCgo+IElmIHRoZSBmaWxlIG1hc2sgaW5jbHVkZXMgdGhl Cj4gLkIgcgo+IHBlcm1pc3Npb24sIHRoZSByZWFkCj4gZmlsZSBtb2RlIHBlcm1pc3Npb24gYml0 IHdpbGwgYmUgc2V0Lgo+IC5JUCBcKGJ1Cj4gSWYgdGhlIGZpbGUgbWFzayBpbmNsdWRlcyB0aGUK PiAuQiB3Cj4gb3IKPiAuQiBwCj4gcGVybWlzc2lvbiwgdGhlIHdyaXRlIGZpbGUgbW9kZSBwZXJt aXNzaW9uIGJpdCB3aWxsIGJlIHNldC4KPiAuSVAgXChidQo+IElmIHRoZSBmaWxlIG1hc2sgaW5j bHVkZXMgdGhlCj4gLkIgeAo+IHBlcm1pc3Npb24sIHRoZSBleGVjdXRlIGZpbGUgbW9kZSBwZXJt aXNzaW9uIGJpdCB3aWxsIGJlIHNldC4KPiAuUFAKPiBJZiB0aGUgQUNMIGNhbiBiZSByZXByZXNl bnRlZCBleGFjdGx5IGJ5IHRoZSBmaWxlIG1vZGUKPiBwZXJtaXNzaW9uIGJpdHMsIHRoZSBmaWxl IHBlcm1pc3Npb24gYml0cyBhcmUgc2V0IHRvIG1hdGNoIHRoZSBBQ0wgYW5kIHRoZSBBQ0wKPiBp cyBub3Qgc3RvcmVkLgoKTWF5YmUgYmV0dGVyOiAiLi4uYW5kIG5vIEFDTCBpcyBzdG9yZWQiCgo+ ICAgICAgICAgICAgICAgIChXaGVuIHRoZSBBQ0wgb2YgYSBmaWxlIGlzIHJlcXVlc3RlZCB3aGlj aCBkb2Vzbid0IGhhdmUgYW4gQUNMLAo+IHRoZSBmaWxlIG1vZGUgcGVybWlzc2lvbiBiaXRzIGFy ZSBjb252ZXJ0ZWQgaW50byBhbiBlcXVpdmFsZW50IEFDTC4pCj4gCj4gLlNTIENoYW5naW5nIHRo ZSBmaWxlIG1vZGUgcGVybWlzc2lvbiBiaXRzCj4gV2hlbiBjaGFuZ2luZyB0aGUgZmlsZSBtb2Rl IHBlcm1pc3Npb24gYml0cyB3aXRoCj4gLkJSIGNobW9kICgxKSwKPiB0aGUgb3duZXIsIGdyb3Vw LCBhbmQgb3RoZXIgZmlsZSBwZXJtaXNzaW9uIGJpdHMgYXJlIHNldCB0byB0aGUgcGVybWlzc2lv biBiaXRzCj4gaW4gdGhlIG5ldyBtb2RlLCBhbmQgdGhlIG93bmVyLCBncm91cCwgYW5kIG90aGVy IGZpbGUgbWFza3MgYXJlIHNldCBiYXNlZCBvbgo+IHRoZSBuZXcgbW9kZSBiaXRzIGFzIGZvbGxv d3M6Cj4gLklQIFwoYnUgNAoKcy80LzIvCgo+IElmIHRoZSByZWFkIGJpdCBpbiBhIHNldCBvZiBw ZXJtaXNzaW9ucyBpcyBzZXQsIHRoZQo+IC5CIHIKPiBwZXJtaXNzaW9uIGluIHRoZSBjb3JyZXNw b25kaW5nIGZpbGUgbWFzayB3aWxsIGJlIHNldC4KPiAuSVAgXChidQo+IElmIHRoZSB3cml0ZSBi aXQgaW4gYSBzZXQgb2YgcGVybWlzc2lvbnMgaXMgc2V0LCB0aGUKPiAuQiB3Cj4gYW5kCj4gLkIg cAo+IHBlcm1pc3Npb25zIGluIHRoZSBjb3JyZXNwb25kaW5nIGZpbGUgbWFzayB3aWxsIGJlIHNl dC4KPiAuSVAgXChidQo+IElmIHRoZSBleGVjdXRlIGJpdCBpbiBhIHNldCBvZiBwZXJtaXNzaW9u cyBpcyBzZXQsIHRoZQo+IC5CIHgKPiBwZXJtaXNzaW9uIGluIHRoZSBjb3JyZXNwb25kaW5nIGZp bGUgbWFzayB3aWxsIGJlIHNldC4KPiAuUFAKPiBJbiBhZGRpdGlvbiwgdGhlCj4gLkIgbWFza2Vk Cj4gYW5kCj4gLkIgd3JpdGVfdGhyb3VnaAo+IEFDTCBmbGFncyBhcmUgc2V0LiBUaGlzIGhhcyB0 aGUKPiBlZmZlY3Qgb2YgbGltaXRpbmcgdGhlIHBlcm1pc3Npb25zIGdyYW50ZWQgYnkgdGhlIEFD TCB0byB0aGUgZmlsZSBtb2RlCj4gcGVybWlzc2lvbiBiaXRzOyBpbiBhZGRpdGlvbiwgdGhlIG93 bmVyIGlzIGdyYW50ZWQgdGhlIG93bmVyIG1vZGUgYml0cyBhbmQKPiBvdGhlcnMgYXJlIGdyYW50 ZWQgdGhlIG90aGVyIG1vZGUgYml0cy4gSWYgdGhlCj4gLkIgYXV0b19pbmhlcml0Cj4gZmxhZyBp cyBzZXQsIHRoZQo+IC5CIHByb3RlY3RlZAo+IGZsYWcgaXMgYWxzbyBzZXQgdG8gcHJldmVudCB0 aGUgQXV0b21hdGljIEluaGVyaXRhbmNlIGFsZ29yaXRobSBmcm9tIG1vZGlmeWluZwo+IHRoZSBB Q0wuCj4gCj4gLlNTIFBlcm1pc3Npb25zIGF0IGZpbGUtY3JlYXRpb24gdGltZQo+IFdoZW4gYSBk aXJlY3RvcnkgaGFzIGluaGVyaXRhYmxlIEFDTCBlbnRyaWVzLCB0aGUgZm9sbG93aW5nCgpzL2hh cy9oYXMgYW4vCgo+IGhhcHBlbnMgd2hlbiBhIGZpbGUgb3IgZGlyZWN0b3J5IGlzIGNyZWF0ZWQg aW5zaWRlIHRoYXQgZGlyZWN0b3J5Ogo+IC5SUyA0Cj4gLklQIDEuIDQKPiBBIGZpbGUgY3JlYXRl ZCBpbnNpZGUgdGhhdCBkaXJlY3Rvcnkgd2lsbCBpbmhlcml0IGFsbCBvZiB0aGUgQUNMIGVudHJp ZXMgdGhhdAo+IGhhdmUgdGhlCj4gLkIgZmlsZV9pbmhlcml0Cj4gZmxhZyBzZXQsIGFuZCBhbGwg aW5oZXJpdGFuY2UtcmVsYXRlZCBmbGFncyBpbiB0aGUgaW5oZXJpdGVkIGVudHJpZXMgZmxhZyB3 aWxsCj4gYmUgY2xlYXJlZC4KPiAKPiBBIHN1YmRpcmVjdG9yeSBjcmVhdGVkIGluc2lkZSB0aGF0 IGRpcmVjdG9yeSB3aWxsIGluaGVyaXQgYWxsIG9mIHRoZSBBQ0wKPiBlbnRyaWVzIHRoYXQgZWl0 aGVyIGhhdmUgdGhlCj4gLkIgZGlyX2luaGVyaXQKPiBmbGFnIHNldCwgb3IgdGhlCj4gLkIgZmls ZV9pbmhlcml0Cj4gZmxhZyBzZXQgYW5kIHRoZQo+IC5CIG5vX3Byb3BhZ2F0ZQo+IGZsYWcgbm90 IHNldC4gIEVudHJpZXMgd2hvc2UKPiAuQiBkaXJfaW5oZXJpdAo+IGZsYWcgaXMgc2V0IHdpbGwg aGF2ZSB0aGVpcgo+IC5CIGluaGVyaXRfb25seQo+IGZsYWcgY2xlYXJlZCwgYW5kIGVudHJpZXMg d2hvc2UKPiAuQiBkaXJfaW5oZXJpdAo+IGZsYWcgaXMgbm90IHNldCB3aWxsIGhhdmUgdGhlaXIK PiAuQiBpbmhlcml0X29ubHkKPiBmbGFnIHNldC4gIEZpbmFsbHksIGVudHJpZXMgd2hvc2UKPiAu QiBub19wcm9wYWdhdGUKPiBmbGFnIGlzIHNldCB3aWxsIGhhdmUgYWxsIGluaGVyaXRhbmNlLXJl bGF0ZWQgZmxhZ3MgY2xlYXJlZC4KPiAuSVAgMi4KPiBJZiB0aGUgcGFyZW50IGRpcmVjdG9yeSdz IEFDTCBoYXMgdGhlCj4gLkIgYXV0b19pbmhlcml0Cj4gZmxhZyBzZXQsIHRoZSBpbmhlcml0ZWQg QUNMIHdpbGwgaGF2ZSBpdHMKPiAuQiBhdXRvX2luaGVyaXQKPiBmbGFnIHNldCwgYW5kIGFsbCBl bnRyaWVzIHdpbGwgaGF2ZSB0aGVpcgo+IC5CIGluaGVyaXRlZAo+IGZsYWcgc2V0LiAgT3RoZXJ3 aXNlLCB0aGUKPiAuQiBhdXRvX2luaGVyaXQKPiBhbmQKPiAuQiBpbmhlcml0ZWQKPiBmbGFncyBh cmUgY2xlYXJlZC4KPiAuSVAgMy4KPiBUaGUgdGhyZWUgZmlsZSBtYXNrcyBhcmUgY29tcHV0ZWQg ZnJvbSB0aGUgaW5oZXJpdGVkIEFDTCBhcyBkZXNjcmliZWQgaW4KPiB0aGUgc2VjdGlvbgo+IC5J UiAiQ29tcHV0aW5nIHRoZSBtYXhpbXVtIGZpbGUgbWFza3MiIC4KPiAuSVAgNC4KPiBUaGUgdGhy ZWUgc2V0cyBvZiBwZXJtaXNzaW9ucyBmb3IgdGhlIG93bmVyLCB0aGUgZ3JvdXAsIGFuZCBmb3Ig b3RoZXJzIGluCj4gdGhlIFxmSW1vZGVcZlIgcGFyYW1ldGVyIGFzIGdpdmVuIHRvCj4gLkJSIG9w ZW4gKDIpLAo+IC5CUiBta2RpciAoMiksCj4gYW5kIHNpbWlsYXIgYXJlIGNvbnZlcnRlZCBpbnRv IHNldHMgb2YgUmljaEFDTCBwZXJtaXNzaW9ucy4gVGhlIGNvcnJlc3BvbmRlbmNlCj4gYmV0d2Vl biBtYXNrIGZsYWdzIGFuZCBSaWNoQUNMIHBlcm1pc3Npb24gYml0cyBpcyBkZXNjcmliZWQgaW4g dGhlIHNlY3Rpb24KPiAuSVIgIkNoYW5naW5nIHRoZSBmaWxlIG1vZGUgcGVybWlzc2lvbiBiaXRz IiAuCj4gQW55IFJpY2hBQ0wgcGVybWlzc2lvbnMgbm90IGluY2x1ZGVkIGluIHRob3NlIHNldHMg YXJlCj4gcmVtb3ZlZCBmcm9tIHRoZSBvd25lciwgZ3JvdXAsIGFuZCBvdGhlciBmaWxlIG1hc2tz LiBUaGUgZmlsZSBtb2RlIHBlcm1pc3Npb24KPiBiaXRzIGFyZSB0aGVuIGNvbXB1dGVkIGZyb20g dGhlIGZpbGUgbWFza3MgYXMgZGVzY3JpYmVkIGluIHRoZSBzZWN0aW9uCj4gLklSICJBc3NpZ25p bmcgYW4gQWNjZXNzIENvbnRyb2wgTGlzdCIgLgo+IFRoZSBwcm9jZXNzIHVtYXNrIChzZWUKPiAu QlIgdW1hc2sgKDIpKQo+IGlzIGlnbm9yZWQuCj4gLklQIDUuCj4gVGhlCj4gLkIgbWFza2VkCj4g QUNMIGZsYWcgaXMgc2V0LiBUaGUKPiAuQiB3cml0ZV90aHJvdWdoCj4gQUNMIGZsYWcgcmVtYWlu cyBjbGVhcmVkLiBJbiBhZGRpdGlvbiwgaWYgdGhlCj4gLkIgYXV0b19pbmhlcml0Cj4gZmxhZyBv ZiB0aGUgaW5oZXJpdGVkIEFDTCBpcyBzZXQsIHRoZQo+IC5CIHByb3RlY3RlZAo+IGZsYWcgaXMg YWxzbyBzZXQgdG8gcHJldmVudCB0aGUgQXV0b21hdGljIEluaGVyaXRhbmNlIGFsZ29yaXRobSBm cm9tIG1vZGlmeWluZwo+IHRoZSBBQ0wuCj4gLlJFCj4gLlBQCj4gV2hlbiBhIGRpcmVjdG9yeSBk b2VzIG5vdCBoYXZlIGluaGVyaXRhYmxlIEFDTCBlbnRyaWVzLCBmaWxlcyBhbmQgZGlyZWN0b3Jp ZXMKPiBjcmVhdGVkIGluc2lkZSB0aGF0IGRpcmVjdG9yeSB3aWxsIG5vdCBiZSBhc3NpZ25lZCBB Y2Nlc3MgQ29udHJvbCBMaXN0cyBhbmQgdGhlCj4gZmlsZSBtb2RlIHBlcm1pc3Npb24gYml0cyB3 aWxsIGJlIHNldCB0byAoXGZJbW9kZVxmUlwgJlwgflxmSXVtYXNrXGZSKSB3aGVyZQo+IFxmSW1v ZGVcZlIgaXMgdGhlIG1vZGUgYXJndW1lbnQgb2YgdGhlIHJlbGV2YW50IHN5c3RlbSBjYWxsIGFu ZCBcZkl1bWFza1xmUiBpcwo+IHRoZSBwcm9jZXNzIHVtYXNrIChzZWUKPiAuQlIgdW1hc2sgKDIp KS4KPiAKPiAuU1MgQXV0b21hdGljIEluaGVyaXRhbmNlCj4gQXV0b21hdGljIEluaGVyaXRhbmNl IGlzIGEgbWVjaGFuaXNtIHRoYXQgYWxsb3dzIHBlcm1pc3Npb24gY2hhbmdlcyB0bwo+IHByb3Bh Z2F0ZSBmcm9tIGEgZGlyZWN0b3J5IHRvIGZpbGVzIGFuZCBzdWJkaXJlY3RvcmllcyBpbnNpZGUg dGhhdCBkaXJlY3RvcnksCj4gcmVjdXJzaXZlbHkuICBQcm9wYWdhdGlvbiBpcyBjYXJyaWVkIG91 dCBieSB0aGUgcHJvY2VzcyBjaGFuZ2luZyB0aGUgZGlyZWN0b3J5Cj4gcGVybWlzc2lvbnMgKHVz dWFsbHksCj4gLkJSIHNldHJpY2hhY2wgKDEpKTsKPiBpdCBoYXBwZW5zIHdpdGhvdXQgdXNlciBp bnRlcnZlbnRpb24gYWxiZWl0IG5vdCBlbnRpcmVseSBhdXRvbWF0aWNhbGx5Lgo+IAo+IEEgc2ln bmlmaWNhbnQgbGltaXRhdGlvbiBpcyB0aGF0IHRoaXMgbWVjaGFuaXNtIHdvcmtzIG9ubHkgYXMg bG9uZyBhcyBmaWxlcwo+IGFyZSBjcmVhdGVkIHdpdGhvdXQgZXhwbGljaXRseSBzcGVjaWZ5aW5n IHRoZSBmaWxlIHBlcm1pc3Npb25zIHRvIHVzZS4gVGhlCj4gc3RhbmRhcmQgc3lzdGVtIGNhbGxz IGZvciBjcmVhdGluZyBmaWxlcyBhbmQgZGlyZWN0b3JpZXMKPiAuUkIgKCBjcmVhdCAoMiksCj4g LkJSIG9wZW4gKDIpLAo+IC5CUiBta2RpciAoMiksCj4gLkJSIG1rbm9kICgyKSkKPiBhbGwgaGF2 ZSBtYW5kYXRvcnkgbW9kZSBwYXJhbWV0ZXJzIHdoaWNoIGRlZmluZSB0aGUgbWF4aW11bSBhbGxv d2VkIHBlcm1pc3Npb25zCj4gb2YgdGhlIG5ldyBmaWxlcy4gVG8gdGFrZSBhY2NvdW50IG9mIHRo aXMgcmVzdHJpY3Rpb24sIHRoZQo+IC5CIHByb3RlY3RlZAo+IEFDTCBmbGFnIG11c3QgYmUgc2V0 IGlmIHRoZQo+IC5CIGluaGVyaXRlZAo+IGZsYWcgaXMgc2V0LiBUaGlzIGVmZmVjdGl2ZWx5IGRp c2FibGVzIEF1dG9tYXRpYyBJbmhlcml0YW5jZSBmb3IgdGhhdAo+IHBhcnRpY3VsYXIgZmlsZS4K PiAKCkFkZCB0aGUgZm9sbG93aW5nIGF0IHRoZSBzdGFydCBvZiB0aGUgbmV4dCBwYXJhZ3JhcGg6 CgoiTW90d2l0aHN0YW5kaW5nIHRoZSBhZm9yZW1lbnRpb25lZCBsaW1pdGF0aW9uLCIKPiBBdXRv bWF0aWMgSW5oZXJpdGFuY2Ugc3RpbGwgcmVtYWlucyB1c2VmdWwgZm9yIG5ldHdvcmsgcHJvdG9j b2xzIGxpa2UgTkZTdjQgYW5kCj4gU01CLCB3aGljaCBib3RoIHN1cHBvcnQgY3JlYXRpbmcgZmls ZXMgYW5kIGRpcmVjdG9yaWVzIHdpdGhvdXQgZGVmaW5pbmcgdGhlaXIKPiBwZXJtaXNzaW9uczog dGhleSBjYW4gaW1wbGVtZW50IHRob3NlIG9wZXJhdGlvbnMgYnkgdXNpbmcgdGhlIHN0YW5kYXJk IHN5c3RlbQoKcy86IHRoZXkvLiBUaGVzZSBwcm90b2NvbHMvCihUbyBhdm9pZCBhbiBleGNlc3Np dmVseSBsb25nIHNlbnRlbmNlLikKCj4gY2FsbHMgYW5kIGJ5IHRoZW4gdW5kb2luZyB0aGUgZWZm ZWN0IG9mIGFwcGx5aW5nIHRoZSBtb2RlIHBhcmFtZXRlcnMuCj4gCj4gV2hlbiB0aGUgQUNMIG9m IGEgZGlyZWN0b3J5IGlzIGNoYW5nZWQsIHRoZSBmb2xsb3dpbmcgaGFwcGVucyBmb3IgZWFjaCBl bnRyeQo+IChcKGxxY2hpbGRcKHJxKSBpbnNpZGUgdGhhdCBkaXJlY3Rvcnk6Cj4gLklQIDEuIDQK PiBJZiB0aGUgZW50cnkgaXMgYSBzeW1ibGljIGxpbmssIHNraXAgdGhlIGNoaWxkLgoKcy9zeW1i bGljL3N5bWJvbGljLwoKPiAuSVAgMi4KPiBJZiB0aGUKPiAuQiBhdXRvX2luaGVyaXQKPiBmbGFn IG9mIHRoZSBlbnRyeSdzIEFDTCBpcyBub3Qgc2V0IG9yIHRoZQo+IC5CIHByb3RlY3RlZAo+IGZs YWcgaXMgc2V0LCBza2lwIHRoZSBjaGlsZC4KPiAuSVAgMy4KPiBXaXRoIHRoZSBjaGlsZCdzIEFD TDoKPiAuUlMgNAo+IC5JUCBhKSA0Cj4gSWYgdGhlCj4gLkIgZGVmYXVsdGVkCj4gZmxhZyBpcyBz ZXQsIHJlcGxhY2UgdGhlIEFDTCB3aXRoIGFuIGVtcHR5IEFDTAo+IHdpdGggdGhlCj4gLkIgYXV0 b19pbmhlcml0Cj4gZmxhZyBzZXQuCj4gLklQIGIpCj4gRGVsZXRlIGFsbCBlbnRyaWVzIHdoaWNo IGhhdmUgdGhlCj4gLkIgaW5oZXJpdGVkCj4gZmxhZyBzZXQuCj4gLklQIGMpCj4gQXBwZW5kIGFs bCBlbnRyaWVzIGluaGVyaXRlZCBmcm9tIHRoZSBwYXJlbnQgZGlyZWN0b3J5IGFjY29yZGluZyB0 byBzdGVwIDEgb2YKPiB0aGUgYWxnb3JpdGhtIGRlc2NyaWJlZCB1bmRlcgo+IC5JUiAiUGVybWlz c2lvbnMgYXQgZmlsZS1jcmVhdGlvbiB0aW1lIi4KPiBTZXQgdGhlCj4gLkIgaW5oZXJpdGVkCj4g ZmxhZyBvZiBlYWNoIG9mIHRoZXNlIGVudHJpZXMuCj4gLklQIGQpCj4gUmVjb21wdXRlIHRoZSBm aWxlIG1hc2tzLgo+IC5SRQo+IC5JUCA0Lgo+IElmIHRoZSBjaGlsZCBpcyBhIGRpcmVjdG9yeSwg cmVjdXJzaXZlbHkgYXBwbHkgdGhpcyBhbGdvcml0aG0uCj4gCj4gLlNTIEFjY2VzcyBjaGVjayBh bGdvcml0aG0KPiAKPiBXaGVuIGEgcHJvY2VzcyByZXF1ZXN0cyBhIHBhcnRpY3VsYXIga2luZCBv ZiBhY2Nlc3MgKGV4cHJlc3NlZCBhcyBhIHNldCBvZgo+IFJpY2hBQ0wgcGVybWlzc2lvbnMpIHRv IGEgZmlsZSwgdGhlIGZvbGxvd2luZyBhbGdvcml0aG0gZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZQo+ IGFjY2VzcyBpcyBncmFudGVkIG9yIGRlbmllZDoKPiAKPiAuSVAgMS4gNAo+IElmIHRoZQo+IC5C IG1hc2tlZAo+IEFDTCBmbGFnIGlzIHNldCwgdGhlbjoKPiAuUlMgNAo+IC5JUCBhKSA0Cj4gSWYg dGhlCj4gLkIgd3JpdGVfdGhyb3VnaAo+IEFDTCBmbGFnIGlzIHNldCwgdGhlbjoKPiAuUlMgNAoK cy80LzIvCgo+IC5JUCBcKGJ1IDQKCnMvNC8yLwoKPiBJZiB0aGUgcmVxdWVzdGluZyBwcm9jZXNz IGlzIHRoZSBmaWxlIG93bmVyLCB0aGVuIGFjY2VzcyBpcyBncmFudGVkIGlmIHRoZQo+IG93bmVy IG1hc2sgaW5jbHVkZXMgdGhlIHJlcXVlc3RlZCBwZXJtaXNzaW9ucywgYW5kIGlzIG90aGVyd2lz ZSBkZW5pZWQuCj4gLklQIFwoYnUKPiBJZiB0aGUgcmVxdWVzdGluZyBwcm9jZXNzIGlzIG5vdCB0 aGUgZmlsZSBvd25lciwgaXMgbm90IGluIHRoZSBvd25pbmcgZ3JvdXAsCj4gYW5kIG5vIEFDTCBl bnRyaWVzIG90aGVyIHRoYW4KPiAuQiBldmVyeW9uZUAKPiBtYXRjaCB0aGUgcHJvY2VzcywgdGhl biBhY2Nlc3MgaXMgZ3JhbnRlZCBpZiB0aGUgb3RoZXIgbWFzayBpbmNsdWRlcyB0aGUKPiByZXF1 ZXN0ZWQgcGVybWlzc2lvbnMsIGFuZCBpcyBvdGhlcndpc2UgZGVuaWVkLgoKU28sIGluIHRoZSBh Ym92ZSBzdWJjYXNlcywgdGhlIGZvbGxvd2luZyBkb2VzIG5vdCBzZWVtIHRvIGJlIGNvdmVyZWQ6 CiAgICAgICAgKDEpICJtYXNrZWQiIEFDTCBmbGFnIGlzIHNldCBBTkQKICAgICAgICAoMikgcmVx dWVzdGluZyBwcm9jZXNzICppcyogaW4gb3duaW5nIGdyb3VwICpvciogYW4gQUNMIG90aGVyCiAg ICAgICAgICAgIHRoYW4gImV2ZXJ5b25lQCJtYXRjaGVzIHRoZSBwcm9jZXNzLgoKV2hhdCBoYXBw ZW5zIGluIHRoaXMgY2FzZT8gSSBzdXNwZWN0IHRoYXQgc29tZWhvdyB3ZSBhcmUgc3VwcG9zZWQg dG8KZmFsbCB0aHJvdWdoIHRvIHBhcnQgImIpIiBiZWxvdyAoYW5kIHBvc3NpYmx5IGludG8gY2xh dXNlICIyLiI/KSwgYnV0CnRoZSBsb2dpY2FsIHN0cnVjdHVyZSBvZiB0aGUgY2xhdXNlcyBkb2Vz IG5vdCByZWZsZWN0IHRoaXMuCiAgICAgICAgCj4gLlJFCj4gLklQIGIpCj4gSWYgYW55IG9mIHRo ZSBmb2xsb3dpbmcgaXMgdHJ1ZToKPiAuUlMgNAoKcy80LzIvCgo+IC5JUCBcKGJ1IDQKCnMvNC8y LwoKPiB0aGUgcmVxdWVzdGluZyBwcm9jZXNzIGlzIHRoZSBmaWxlIG93bmVyIGFuZCB0aGUgb3du ZXIgbWFzayBkb2VzIG5vdCBpbmNsdWRlIGFsbAo+IHJlcXVlc3RlZCBwZXJtaXNzaW9ucywKPiAu SVAgXChidSA0CgpzLyA0Ly8KCj4gdGhlIHJlcXVlc3RpbmcgcHJvY2VzcyBpcyBub3QgdGhlIGZp bGUgb3duZXIgYW5kIGl0IGlzIGluIHRoZSBvd25pbmcgZ3JvdXAgb3IKPiBtYXRjaGVzIGFueSBB Q0wgZW50cmllcyBvdGhlciB0aGFuCj4gLkJSIGV2ZXJ5b25lQCAsCj4gYW5kIHRoZSBncm91cCBt YXNrIGRvZXMgbm90IGluY2x1ZGUgYWxsIHJlcXVlc3RlZCBwZXJtaXNzaW9ucywKPiAuSVAgXChi dSA0CgpzLyA0Ly8KCj4gdGhlIHJlcXVlc3RpbmcgcHJvY2VzcyBpcyBub3QgdGhlIGZpbGUgb3du ZXIsIG5vdCBpbiB0aGUgb3duaW5nIGdyb3VwLCBpdAo+IG1hdGNoZXMgbm8gQUNMIGVudHJpZXMg b3RoZXIgdGhhbgo+IC5CUiBldmVyeW9uZUAgLAo+IGFuZCB0aGUgb3RoZXIgbWFzayBkb2VzIG5v dCBpbmNsdWRlIGFsbCByZXF1ZXN0ZWQgcGVybWlzc2lvbnMsCj4gLlBQCj4gdGhlbiBhY2Nlc3Mg aXMgZGVuaWVkLgo+IC5SRQo+IC5SRQoKQXQgc29tZSBwb2ludCwgcGVyaGFwcyBpbiB0aGUgbmV4 dCBwYXJhZ3JhcGgsIEkgdGhpbmsgdGhhdCBpdCBuZWVkcyB0bwpiZSBjbGFyaWZpZWQgdGhhdCB1 bmxpa2UgUE9TSVggQUNMcywgYSBwcm9jZXNzIGNhbiBnYWluIHRoZSBwZXJtaXNzaW9ucwppdCBy ZXF1aXJlcyBieSBhY2N1bXVsYXRpbmcgdGhlbSBmcm9tIG11bHRpcGxlIFJpY2hBQ0wgZW50aWVz LiAoVGhhdCdzCmNvcnJlY3QsIGlzIGl0IG5vdD8pCgo+IC5JUCAyLgo+IFNldCB0aGUgcmVtYWlu aW5nIHBlcm1pc3Npb25zIHRvIHRoZSByZXF1ZXN0ZWQgcGVybWlzc2lvbnMuICBHbyB0aHJvdWdo IGFsbCBBQ0wKPiBlbnRyaWVzLiBGb3IgZWFjaCBlbnRyeToKClNvLCBwZXJoYXBzIHJlcGxhY2Ug dGhlIHByZWNlZGluZyB0d28gbGluZXMgd2l0aCBzb21ldGhpbmcgbGlrZToKCltbClVwb24gcmVh Y2hpbmcgdGhpcyBwb2ludCwgdGhlIGRldGVybWluYXRpb24gb2Ygd2hldGhlciBvciBub3QgYWNj ZXNzIGlzCmdyYW50ZWQgaXMgbWFkZSBieSBzY2FubmluZyBhbGwgQUNMIGVudHJpZXMgdG8gc2Vl IGlmIG9uZSBvciBtb3JlCmFwcGxpY2FibGUgZW50cmllcyB0b2dldGhlciBncmFudCBhIGN1bXVs YXRpdmUgc2V0IG9mIHBlcm1pc3Npb25zIHRoYXQKbWF0Y2hlcyB0aGUgcmVxdWVzdGVkIHBlcm1p c3Npb25zIG9yIHRoZXJlIGlzIGFuIGFwcGxpY2FibGUgZW50cnkgdGhhdApleHBsaWNpdGx5IGRl bmllcyBvbmUgb3IgbW9yZSBvZiB0aGUgcmVxdWVzdGVkIHBlcm1pc3Npb25zLgpUaGUgc2NhbiBv ZiBhbGwgQUNMIGVudHJpZXMgYmVnaW5zIGJ5CmZpcnN0IGluaXRpYWxpemluZyB0aGUgc2V0IG9m IHJlbWFpbmluZyBwZXJtaXNzaW9ucyAoaS5lLiwgdGhvc2UgdGhhdCBoYXZlCm5vdCB5ZXQgYmVl biBzYXRpc2ZpZWQgZHVyaW5nIHRoZSBzY2FuKSB0byBiZSB0aGUgc2V0IG9mIHJlcXVlc3RlZApw ZXJtaXNzaW9ucy4gVGhlbiB0aGUgQUNMIGVudHJpZXMgYXJlIHNjYW5uZWQKLklSICJpbiBvcmRl ciIgLAphbmQgZm9yIGVhY2ggZW50cnk6Cl1dCgo+IC5SUyA0Cj4gLklQIGEpIDQKPiBJZiB0aGUK PiAuQiBpbmhlcml0X29ubHkKPiBvcgo+IC5CIHVubWFwcGVkCj4gZmxhZ3MgYXJlIHNldCwgY29u dGludWUgd2l0aCB0aGUgbmV4dCBBQ0wgZW50cnkuCj4gLklQIGIpCj4gSWYgYW55IG9mIHRoZSBm b2xsb3dpbmcgaXMgdHJ1ZToKPiAuUlMgNAoKcy80LzIvCgo+IC5JUCBcKGJ1IDQKCnMvNC8yLwoK PiB0aGUgZW50cnkncyBpZGVudGlmaWVyIGlzCj4gLkIgb3duZXJACj4gYW5kIHRoZSByZXF1ZXN0 aW5nIHByb2Nlc3MgaXMgdGhlIGZpbGUgb3duZXIsCj4gLklQIFwoYnUKPiB0aGUgZW50cnkncyBp ZGVudGlmaWVyIGlzCj4gLkIgZ3JvdXBACj4gYW5kIHRoZSByZXF1ZXN0aW5nIHByb2Nlc3MgaXMg aW4gdGhlIG93bmluZyBncm91cCwKPiAuSVAgXChidQo+IHRoZSBlbnRyeSdzIGlkZW50aWZpZXIg aXMgYSB1c2VyIGFuZCB0aGUgcmVxdWVzdGluZyBwcm9jZXNzIGlzIG93bmVkIGJ5IHRoYXQKPiB1 c2VyLAo+IC5JUCBcKGJ1Cj4gdGhlIGVudHJ5J3MgaWRlbnRpZmllciBpcyBhIGdyb3VwIGFuZCB0 aGUgcmVxdWVzdGluZyBwcm9jZXNzIGlzIGEgbWVtYmVyIGluCj4gdGhhdCBncm91cCwKPiAuSVAg XChidQo+IHRoZSBlbnRyeSdzIGlkZW50aWZpZXIgaXMKPiAuQlIgZXZlcnlvbmVAICwKPiAuUFAK PiB0aGVuIHRoZSBlbnRyeSBtYXRjaGVzIHRoZSBwcm9jZXNzOyBwcm9jZWVkIHRvIHRoZSBuZXh0 IHN0ZXAuIE90aGVyd2lzZSwKPiBjb250aW51ZSB3aXRoIHRoZSBuZXh0IEFDTCBlbnRyeS4KPiAu UkUKPiAuSVAgYykKPiBJZiB0aGUgZW50cnkgZGVuaWVzIGFueSBvZiB0aGUgcmVtYWluaW5nIHBl cm1pc3Npb25zLCBhY2Nlc3MgaXMgZGVuaWVkLgo+IC5JUCBkKQo+IElmIHRoZSBlbnRyeSBhbGxv d3MgYW55IG9mIHRoZSByZW1haW5pbmcgcGVybWlzc2lvbnMsIHRoZW46Cj4gLlJTIDQKCnMvNC8y LwoKPiAuSVAgXChidSA0CgpzLzQvMi8KCj4gSWYgdGhlCj4gLkIgbWFza2VkCj4gQUNMIGZsYWcg aXMgc2V0IGFuZCB0aGUgZW50cnkncyBpZGVudGlmaWVyIGlzIG5vdAo+IC5CIG93bmVyQAo+IG9y Cj4gLkJSIGV2ZXJ5b25lQAo+IG9yIGlzIGEgdXNlciBlbnRyeSBtYXRjaGluZyB0aGUgZmlsZSBv d25lciwgcmVtb3ZlIGFsbCBwZXJtaXNzaW9ucyBmcm9tIHRoZQo+IHJlbWFpbmluZyBwZXJtaXNz aW9ucyB3aGljaCBhcmUgYm90aCBhbGxvd2VkIGJ5IHRoZSBlbnRyeSBhbmQgaW5jbHVkZWQgaW4g dGhlCj4gZ3JvdXAgbWFzaywKPiAuSVAgXChidQo+IE90aGVyd2lzZSwgcmVtb3ZlIGFsbCBwZXJt aXNzaW9ucyBmcm9tIHRoZSByZW1haW5pbmcgcGVybWlzc2lvbnMgd2ljaCBhcmUKCnMvd2ljaC93 aGljaCAKCj4gYWxsb3dlZCBieSB0aGUgZW50cnkuCj4gLlJFCj4gLlJFCj4gLklQIDMuCj4gSWYg dGhlcmUgYXJlIG5vIG1vcmUgcmVtYWluaW5nIHBlcm1pc3Npb25zLCBhY2Nlc3MgaXMgYWxsb3dl ZC4gT3RoZXJ3aXNlLAo+IGFjY2VzcyBpcyBkZW5pZWQuCj4gCj4gLlNTIENvbXB1dGluZyB0aGUg bWF4aW11bSBmaWxlIG1hc2tzCj4gV2hlbiBzZXR0aW5nIGFuIEFDTCBhbmQgbm8gZmlsZSBtYXNr cyBoYXZlIGJlZW4gZXhwbGljaXRseSBzcGVjaWZpZWQgYW5kIHdoZW4KPiBpbmhlcml0aW5nIGFu IEFDTCBmcm9tIHRoZSBwYXJlbnQgZGlyZWN0b3J5LCB0aGUgZm9sbG93aW5nIGFsZ29yaXRobSBp cyB1c2VkCj4gZm9yIGNvbXB1dGluZyB0aGUgZmlsZSBtYXNrczoKPiAKPiAuSVAgMS4gNAo+IENs ZWFyIHRoZSBvd25lciwgZ3JvdXAsIGFuZCBvdGhlciBmaWxlIG1hc2tzLiBSZW1lbWJlciB3aGlj aCBwZXJtaXNzaW9ucyBoYXZlCj4gYWxyZWFkeSBiZWVuIHByb2Nlc3NlZCAoaW5pdGlhbGx5LCB0 aGUgZW1wdHkgc2V0KS4KPiAuSVAgMi4KPiBGb3IgZWFjaCBBQ0wgZW50cnk6Cj4gLlJTIDQKCnMv NC8yLwoKPiAuSVAgXChidSA0CgpzLzQvMi8KCj4gSWYgdGhlCj4gLkIgaW5oZXJpdF9vbmx5Cj4g ZmxhZyBpcyBzZXQsIHNraXAgdGhlIGVudHJ5Lgo+IC5JUCBcKGJ1IDQKCnMvIDQvLwoKPiBPdGhl cndpc2UsIGNvbXB1dGUgd2hpY2ggcGVybWlzc2lvbnMgdGhlIGVudHJ5IGFsbG93cyBvciBkZW5p ZXMgdGhhdCBoYXZlIG5vdAo+IGJlZW4gcHJvY2Vzc2VkIHlldCAodGhlIHJlbWFpbmluZyBwZXJt aXNzaW9ucykuCj4gLklQIFwoYnUKPiBJZiB0aGUgZW50cnkgaXMgYW4KPiAuQiBvd25lckAKPiBl bnRyeSwgYWRkIHRoZSByZW1haW5pbmcgcGVybWlzc2lvbnMgdG8gdGhlIG93bmVyIG1hc2sgZm9y Cj4gLkIgYWxsb3cKPiBlbnRyaWVzLCBhbmQgcmVtb3ZlIHRoZSByZW1haW5pbmcgcGVybWlzc2lv bnMgZnJvbSB0aGUgb3duZXIgbWFzayBmb3IKPiAuQiBkZW55Cj4gZW50cmllcy4KPiAuSVAgXChi dQo+IE90aGVyd2lzZSwgaWYgdGhlIGVudHJ5IGlzIGFuCj4gLkIgZXZlcnlvbmVACj4gZW50cnks IHByb2NlZWQgYXMgd2l0aAo+IC5CIG93bmVyQAo+IGVudHJpZXMgYnV0IGFkZCBvciByZW1vdmUg dGhlIHJlbWFpbmluZyBwZXJtaXNzaW9ucyBmcm9tIHRoZSBvd25lciwgZ3JvdXAsIGFuZAo+IG90 aGVyIGZpbGUgbWFza3MuCj4gLklQIFwoYnUKPiBPdGhlcndpc2UsIHByb2NlZWQgYXMgd2l0aAo+ IC5CIG93bmVyQAo+IGVudHJpZXMgYnV0IGFkZCBvciByZW1vdmUgdGhlIHJlbWFpbmluZyBwZXJt aXNzaW9ucyBmcm9tIHRoZSBvd25lciBhbmQgZ3JvdXAKPiBmaWxlIG1hc2tzLgo+IC5JUCBcKGJ1 Cj4gQWRkIHRoZSBlbnRyeSdzIHBlcm1pc3Npb25zIHRvIHRoZSBwcm9jZXNzZWQgcGVybWlzc2lv bnMuCj4gLlJFCj4gLlBQCj4gVGhlIHJlc3VsdGluZyBmaWxlIG1hc2tzIHJlcHJlc2VudCB0aGUg QUNMIGFzIGNsb3NlbHkgYXMgcG9zc2libGUuIFdpdGggdGhlc2UKPiBmaWxlIG1hc2tzLCBpZiB0 aGUKPiAuQiBtYXNrZWQKPiBBQ0wgZmxhZyBpcyBzZXQsIHRoZSBlZmZlY3RpdmUgcGVybWlzc2lv bnMgc3RpbGwgc3RheSB0aGUgc2FtZS4KClRoZSBtZWFpbmcgb2YgIndpbGwgc3RheSB0aGUgc2Ft ZSIgaXMgbm90IHF1aXRlIGNsZWFyICJ3aWxsIHN0YXkgdGhlCnNhbWUgKmFzIHdoYXQqIj8pLiBJ IHN1c3BlY3QgSSBrbm93IHdoYXQgeW91IG1lYW4sIGJ1dCBpdCBuZWVkcyB0byBiZQptYWRlIG1v cmUgb2J2aW91cy4KCj4gCj4gLlwiIC5TSCBCVUdTCj4gLlNIIEFVVEhPUgo+IFdyaXR0ZW4gYnkg QW5kcmVhcyBHcsO8bmJhY2hlciA8YWdydWVuYmFAcmVkaGF0LmNvbT4uCj4gCj4gUGxlYXNlIHNl bmQgeW91ciBidWcgcmVwb3J0cywgc3VnZ2VzdGVkIGZlYXR1cmVzIGFuZCBjb21tZW50cyB0byB0 aGUgYWJvdmUgYWRkcmVzcy4KPiAKCkknbSBnb2luZyB0byBwbGF5IHRoZSBicm9rZW4gcmVjb3Jk IDotKQoKQ291bGQgd2Ugc3RhcnQgd2l0aCBqdXN0IGEgZmV3IHNpbXBsZSBleGFtcGxlcyBhbHJl YWR5LCBhbmQgYnVpbGQgdXAKb3ZlciBmdXR1cmUgaXRlcmF0aW9ucyBvZiB0aGlzIHBhZ2U/Cgo+ IC5TSCBDT05GT1JNSU5HIFRPCj4gUmljaCBBY2Nlc3MgQ29udHJvbCBMaXN0cyBhcmUgTGludXgt c3BlY2lmaWMuCj4gLlNIIFNFRSBBTFNPCj4gLkJSIGFjbCAoNSksCgpNb3ZlIHRoaXMgZW50cnkg dG8gdGhlIHBvaW50IFhYWCBiZWxvdy4KCj4gLkJSIGNobW9kICgxKSwKPiAuQlIgZ2V0cmljaGFj bCAoMSksCj4gLkJSIGxzICgxKSwKPiAuQlIgc2V0cmljaGFjbCAoMSkKPiAuQlIgc3RhdCAoMiks Cj4gLkJSIHVtYXNrICgyKQo+IC5cIiBsaWJyaWNoYWNsCgpYWFgKCkJ5IHRoZSB3YXksIGFyZSB0 aGVyZSBhbHJlYWR5IG1hbiBwYWdlcyBmb3IgdGhlIGxpYnJpY2hhY2wgZnVuY3Rpb25zPwoKQ2hl ZXJzLAoKTWljaGFlbAoKLS0gCk1pY2hhZWwgS2VycmlzawpMaW51eCBtYW4tcGFnZXMgbWFpbnRh aW5lcjsgaHR0cDovL3d3dy5rZXJuZWwub3JnL2RvYy9tYW4tcGFnZXMvCkxpbnV4L1VOSVggU3lz dGVtIFByb2dyYW1taW5nIFRyYWluaW5nOiBodHRwOi8vbWFuNy5vcmcvdHJhaW5pbmcvCgpfX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwp4ZnMgbWFpbGluZyBs aXN0Cnhmc0Bvc3Muc2dpLmNvbQpodHRwOi8vb3NzLnNnaS5jb20vbWFpbG1hbi9saXN0aW5mby94 ZnMK