-
Notifications
You must be signed in to change notification settings - Fork 0
Library Design Draft
All functions return an instance of cryfs_status, which represents success or an error code.
enum cryfs_status {0: success, error codes ...};
cryfs_status cryfs_load_init(cryfs_load_context **);
cryfs_status cryfs_load_set_basedir(cryfs_load_context *context, const char *basedir, size_t basedir_length);
cryfs_status cryfs_load_set_password(cryfs_load_context *context, const char *password, size_t password_length);
cryfs_status cryfs_load_set_externalconfig(cryfs_load_context *context, const char *configfile, size_t configfile_length);
// Load it. This also initializes the mount handle you pass it. You don't have ownership of the mount_handle and don't have to free it.
cryfs_status cryfs_load(cryfs_load_context *context, cryfs_mount_handle **handle);
// Use the mount_handle ...
// ... and in the end, free the context
void cryfs_load_free(cryfs_load_context *);
// Create a file system
cryfs_status *cryfs_create_init(cryfs_create_context **);
// Set options
cryfs_status cryfs_create_set_basedir(cryfs_create_context *context, const char *basedir, size_t basedir_length);
cryfs_status cryfs_create_set_password(cryfs_create_context *context, const char *password, size_t password_len);
cryfs_status cryfs_create_set_externalconfig(cryfs_create_context *context, const char *configfile, size_t configfile_length);
cryfs_status cryfs_create_set_ciphername(cryfs_create_context *context, const char *ciphername, size_t ciphername_length);
... (to be extended in future versions)
// Create it. This also initializes the mount handle you pass it. You don't have ownership of the mount_handle and don't have to free it.
cryfs_status *cryfs_create(cryfs_create_context *context, cryfs_mount_handle **handle);
// After you (possibly) used the mount_handle, you call
void cryfs_create_free(cryfs_create_context *);
// This can be used to check that the cipher is the one you expect.
// *output is initialized to a string containing the cipher name.
// Ownership of this string is kept inside the library. It is valid as long as your cryfs_load_context is valid.
cryfs_status cryfs_mount_get_ciphername(cryfs_mount_handle *handle, const char **output);
... (add more functions returning information about the file system)
// Set mount options
cryfs_status cryfs_mount_set_logfile(cryfs_mount_handle *handle, const char *logfile, size_t logfile_length);
cryfs_status cryfs_mount_set_unmount_idle(cryfs_mount_handle *handle, uint32_t unmount_idle_sec);
... (to be extended in future versions)
// Mount it
cryfs_status cryfs_mount(cryfs_mount_handle *handle, const char *mountdir, size_t mountdir_length);
cryfs_status cryfs_unmount(const char *mountdir, size_t mountdir_length);
cryfs_load_context *ctx;
cryfs_status status;
status = cryfs_load_init(&ctx);
if (status != cryfs_success) {...}
status = cryfs_load_set_basedir(ctx, basedir, strlen(basedir));
if (status != cryfs_success) {...}
status = cryfs_load_set_password(ctx, password, strlen(password));
if (status != cryfs_success) {...}
... (set other things)
cryfs_mount_handle *handle;
status = cryfs_load(ctx, &handle);
if (status != cryfs_success) {...}
status = cryfs_mount_set_unmount_idle(handle, 30);
if (status != cryfs_success) {...}
status = cryfs_mount(handle);
if (status != cryfs_success) {...}
cryfs_load_free(ctx);
cryfs_create_context *ctx;
cryfs_status status;
status = cryfs_create_init(&ctx);
if (status != cryfs_success) {...}
status = cryfs_create_set_basedir(ctx, basedir, strlen(basedir));
if (status != cryfs_success) {...}
status = cryfs_create_set_password(ctx, password, strlen(password));
if (status != cryfs_success) {...}
status = cryfs_create_set_cipher(ctx, cipher, strlen(cipher));
if (status != cryfs_success) {...}
... (set other things)
cryfs_mount_handle *handle;
status = cryfs_create(ctx, &handle);
if (status != cryfs_success) {...}
status = cryfs_mount_set_unmount_idle(handle, 30);
if (status != cryfs_success) {...}
status = cryfs_mount(handle);
if (status != cryfs_success) {...}
cryfs_load_free(ctx);
Note:
This is quite a lot of error checking, which in many places seems unnecessary, since we're only setting values on the context struct to be used later in a call to cryfs_load or cryfs_create. Should we keep it this way? Can we avoid that? Can we say simple setter-functions (like cryfs_load_set_password) that just set some state on the context to be used later (in cryfs_load(context)) can't fail and don't return cryfs_status?
If a user sets a wrong password, we can't fail immediately anyhow (we'll only notice later, when they use the context with the invalid password in a call to cryfs_load(context)). However, when they call cryfs_create_set_cipher(ctx, "invalid-cipher"), we could theoretically fail immediately and not wait until they call cryfs_load with it, and failing earlier is probably better.
On the other hand, if we see the cryfs_context just as a workaround for having a struct, then it wouldn't make sense to fail when users write invalid values to the struct, but it would make sense to fail once they use an invalid struct to load a file system. What do you think?