Projects/Profile Includes
An announcement has been sent to krbdev@mit.edu starting a review of this project. That review will conclude on 2010-08-27.
Comments can be sent to krbdev@mit.edu.
Background
In a July 2010 mailing list discussion about dynamic module discovery, consensus was reached that the profile library should gain support for include-file functionality with the ability to include a variable set of files within a directory. This project is to add that support.
Interface Design
A profile file may contain a line "include FILENAME". FILENAME is read, and line from the file are parsed as if they belonged to the original profile file. If FILENAME does not exist or cannot be read, profile parsing fails.
A profile file may include a line "includedir DIRNAME". If DIRNAME does not exist or is unreadable, profile parsing fails. Files within DIRNAME, whose names consist only of alphanumeric characters and underscores, are read and parsed as if they belonged to the original profile file. The naming restrictions are to avoid parsing editor backup files, .rpmsave files, and the like. If any file cannot be read, profile parsing fails.
An included file may add variable assignments to an existing section simply by switching to that section and making variable assignments within it. This functionality already exists within the profile library.
Currently there is no way to remove or replace an existing value from within an included file. This project does not propose to add that functionality.
Currently, the profile library recognizes when a profile file changes by stat()ing the file on each profile_get_value() call (though no more than once per second). If the file has changed, it is reread. The profile library will not automatically recognize when included files have changed.
The profile library has support for writing a profile file to disk using profile_flush() or a similar function. If such a function is used, the profile contents will be "flattened" into one file with no include directives. This is consistent with other limitations of profile_flush() such as not remembering comments.
Implementation Design
All necessary changes can be made within util/profile/prof_parse.c.
The main body of profile_parse_file() needs to be split out to allow parsing a file's contents into an already existing state structure. The new helper function has the signature:
static errcode_t parse_file(FILE *f, struct parse_state *state);
parse_line() recognizes lines beginning with "include" and passes the following text to a new function parse_include().
parse_include() uses the POSIX.2 function glob() to expand the pattern into a list of filenames, opens each file, and calls parse_file() to parse its contents into the existing state structure.
Open Issues
- glob() may not exist on all systems. Does it exist on Windows? If it does not exist, what fallback position should the code take? Options are:
- Fail to compile if glob() does not exist.
- Disable include support if glob() does not exist.
- Allow only includes of explicit filenames if glob() does not exist.
- Provide a glob() implementation if it does not exist. This may be a substantial amount of code.
- The syntax "include PATTERN" is simple and clear, but may not be optimal. It could break existing profile files which contain an "initial comment" (any text before the first line beginning with '[') with a line which happens to begin with "include". Also, adding an include directive anywhere other than the beginning of a krb5.conf file would cause earlier versions of krb5 to generate a syntax error. Other syntax options include:
- Masquerade as a comment: #include PATTERN
- Masquerade as a section: [include PATTERN]
- Distinctive punctuation: @include PATTERN
- Nothing in the design prevents include directives containing relative paths or patterns. Such an include directive would have unpredictable effects since the current working directory would be different for different invocations of the krb5 library. Should the profile library protect the administrator by restricting include directives to absolute paths? If so, how should it portably recognize an absolute path?
- Should an include directive ever result in a fatal error? Possible error cases include:
- Including an explicit filename (not a pattern) which does not exist.
- Including a pattern which has no matches. Note that it is impossible to distinguish this case from the previous one without breaking the abstraction barrier of glob().
- Including a pattern or filename which attempts to descend into directories which the process has no permission to read.
- Including a pattern or filename which matches a file, but the file cannot be opened.
Note that because of the profile library architecture, it cannot generate extended errors.