#includeboolean_t registry_get( regCred a, char* key, char* valbuff, int leng); boolean_t registry_get_realloc( regCred a, char* key, char** valbuff, int* leng, uint4 kma_flags); boolean_t registry_set( regCred a, const char* key, const char* value); boolean_t registry_delete( regCred a, const char* key); char* registry_walkinit( regCred a, const char* prefix); boolean_t registry_walknext( regCred a, const char* cookie, char* keybuff, int leng); boolean_t registry_walknext_realloc( regCred a, const char* cookie, char** keybuff, int* leng, uint4 kma_flags); void registry_walkend( regCred a, const char* cookie); boolean_t registry_load( regCred a, const char* password); boolean_t registry_commit( regCred a, const char* password); regTransaction* regx_create( regCred a); boolean_t regx_set( regTransaction* t, const char* key, const char* value); boolean_t regx_delete( regTransaction* t, const char* key); errors_t* regx_commit( regTransaction* t, const char* pwd, boolean_t rollback); boolean_t regx_destroy( regTransaction* t); char* errors_readable( errors_t* e); void errors_free( errors_t* e); int errors_iterator( void** cookie, errors*t errs, char** name, char** value);
There are two ways of setting and deleting values - your use depends on how much control you want over the transaction. The registry_set(), registry_delete(), and registry_commit() functions will set and delete values, and if during the commit there is a failure in any individual operation, the rest of the sets and deletes will still get applied.
If, however, you want to make sure that all of the sets and deletes either get applied completely or don't get applied at all, you will want to use the regx_set(), regx_delete(), and regx_commit() functions. With these functions, any error in an individual operation will cause the entire set of operations to be "backed out".
The regCred argument to each function conveys credentials for access control, to be used for checking access permissions when registry values are obtained or set. This is a placeholder for an unimplemented access control mechanism. For the moment, the global value rootCred should be used as the value for the regCred argument, when any of these functions are called.
All arguments and return values are character strings, except for boolean_t values that indicate success/failure. This makes it easy to support the same API with Java (see the javadoc documentation for the netapp.util.Registry class) and with remote API mechanisms. (The C-oriented convention of passing in a buffer and its length for obtaining values from registry_get and registry_walknext is not used in the Java API.)
The registry_get function obtains the value for a particular key in the registry. If an entry for that key exists, B_TRUE is returned and a NULL-terminated series of bytes is copied into valbuff. If the key doesn't exist in the registry, B_FALSE is returned, and errno is set to indicate the type of error. The leng parameter conveys the size of valbuff. If the key's value exceeds that length, it is truncated and copied into valbuff , but B_FALSE is returned and errno is set to ETRUNCATED.
The registry_get_realloc function works like registry_get, except that it will automatically allocate and re-allocate the buffer, as needed. This allows you to get any registry value without knowing how big it is going to be. If you initialize the contents of *valbuff to NULL, then registry_get_realloc will allocate the buffer and re-allocate it as necessary. If *valbuff is non-NULL, then registry_get_realloc will start with that buffer and re-allocate it (with kmem_realloc) only if necesssary. The value of *leng is updated with the final size of the allocated buffer. It is the responsibility of the caller to free the memory allocated by registry_get_realloc (even if the return value of this function is B_FALSE), whenever *valbuff ends up being non-NULL.
The registry_set function sets the value for a particular key in the registry. The return value is a boolean_t value indicating success or failure. If there is a failure, a syslog message will be generated. The maximum lengths of key and value strings are defined by the macros REGISTRY_MAX_KEYSIZE and REGISTRY_MAX_VALSIZE. The registry_set function checks to make sure these lengths are not exceeded.
The registry_delete function deletes a particular key. The return value is a boolean_t value indicating success or failure. (Trying to delete a non-existent key is considered a failure.) If there is a failure, a syslog message will be generated.
The registry can be traversed. To begin a traversal, the registry_walkinit function is called, specifying a prefix. The traversal will return all items in the registry whose names begin with that prefix. The return value of registry_walkinit is a character string used as a magic cookie. That cookie value is given to the registry_walknext function, which should be called repeatedly to do the actual traversal, and which will obtain the key of each item in sorted order. The keybuff and leng parameters of registry_walknext provide the buffer into which the key is copied. (See the description of registry_get above for the exact semantics of how this buffer is treated.) The return value of registry_walknext will be B_TRUE as long as key values are successfully obtained. As soon as there are no more key values, the return value will be B_FALSE, with errno set to ENOENT. If any other type of error occurs during a walk, the return value will be B_FALSE and errno will be set to something other than ENOENT. When registry_walknext returns B_FALSE for any reason, the traversal is terminated and any storage associated with the cookie is reclaimed. If you want to terminate a traversal prematurely, you should call registry_walkend with the cookie value, to allow the cookie storage to be reclaimed,
The registry_walknext_realloc function works like registry_walknext, except that it will automatically allocate and re-allocate the buffer, as needed. This allows you to walk any registry namespace without knowing how big the key strings are going to be. If you initialize the contents of *valbuff to NULL, then registry_walknext_realloc will allocate the buffer and re-allocate it as necessary. If *valbuff is non-NULL, then registry_walknext_realloc will start with that buffer and reallocate it (with kmem_realloc) only if necesssary. The value of *leng is updated with the final size of the allocated buffer. It is the responsibility of the caller to free the memory allocated by registry_walknext_realloc (even if the return value of this function is B_FALSE), whenever *valbuff ends up being non-NULL.
The registry_load function, which is normally only executed when ONTAP boots, reads the contents of the persistent registry file and populates the in-core registry. The second argument is the password used to decrypt the registry - if the value is NULL, the appliance's root password will be used. The registry_commit function does the exact opposite - it writes the in-core registry back into the /etc/registry file. The second argument is the password used to encrypt the registry - if the value is NULL, the appliance's root password will be used. Encryption is not enabled by default - it can be enabled by setting an Open Firmware variable named "registryencrypt?" to "true", or by creating a file /etc/.registry.enable.encryption.
The regx_create function is used to create a transaction. The regx_set and regx_delete functions are used to add "sets" and "deletes" to a transaction. When you are ready to apply the transaction, you call regx_commit. At that point, validation (dependent on the particular registry namespaces being affected) is done on the individual set and delete operations. If any validation fails, the transaction is destroyed and the set of errors is returned. If all validations succeed, an attempt is then made to "commit" the changes. If any of the "commit" operations fail, the transaction is destroyed, any values that were successfully "committed" are restored to their previous values, and the set of errors is returned.
The rollback argument to regx_commit actually determines whether any failures in individual validations or commits will cause the entire transaction to be "rolled back". If rollback is B_FALSE, then the transaction will continue on in spite of any individual errors. In this case, the return value of regx_commit will contain the set of errors that occured.