diff --git a/src/api/encryption.c b/src/api/encryption.c index e576c3deceb48079aff4db30c1bf8a0a77404e1e..0951f062d436a953816231e6ad18c1c842132fd8 100644 --- a/src/api/encryption.c +++ b/src/api/encryption.c @@ -13,16 +13,53 @@ int callback_encryption(const struct _u_request * request, struct _u_response * response, void * user_data) { - char * encryption_status; + bool encrypted; + bool * can_encrypt_nullable = NULL; + bool can_encrypt = true; + json_t * messages = json_array(); + if (path_exists(DATA_PARTITION_DEVICE) && is_encrypted_device(DATA_PARTITION_DEVICE)) { - encryption_status = "encrypted"; + encrypted = true; } else { - encryption_status = "unencrypted"; + encrypted = false; + can_encrypt_nullable = &can_encrypt; + + // Mount the filesystem on the unencrypted device. + int r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_MOUNTPOINT, + FILESYSTEM_TYPE); + if (r != 0) + { + printf("mounting root device failed: return code %d\n", r); + return send_simple_response(response, 500, "error", + "mounting root device failed"); + } + bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT, + MEMORY_USAGE, true); + umount(UNENCRYPTED_MOUNTPOINT); + if (! fits) + { + can_encrypt = false; + json_array_append_new(messages, json_string( + "existing files do not fit in memory")); + } } - return send_simple_response(response, 200, - "encryption-status", encryption_status); + + json_t * json_body = NULL; + json_body = json_object(); + + json_object_set_new(json_body, "encrypted", + encrypted ? json_true() : json_false()); + + json_object_set_new(json_body, "can-encrypt", + can_encrypt_nullable == NULL ? json_null() : + (can_encrypt ? json_true() : json_false())); + json_object_set_new(json_body, "messages", messages); + + ulfius_set_json_body_response(response, 200, json_body); + json_decref(json_body); + return U_CALLBACK_CONTINUE; } diff --git a/src/api/encryption_init.c b/src/api/encryption_init.c index f708cd0d5e1cfc7d1282ebe01f8085eea74ee606..92d1d0ff861dfd3bcf49f378b817c4426f46b4fc 100644 --- a/src/api/encryption_init.c +++ b/src/api/encryption_init.c @@ -63,22 +63,9 @@ int callback_encryption_init(const struct _u_request * request, } // Determine the filesystem usage of the device to be encrypted. - unsigned long size = filesystem_usage(UNENCRYPTED_MOUNTPOINT); - if (size < 0) - { - // Something went wrong in determining the filesystem usage. - printf("determining filesystem usage failed: return code %lu\n", size); - return send_simple_response(response, 500, "error", - "determining filesystem usage failed"); - } - printf("root device usage: %lu bytes\n", size); - - // Determine the available memory. - unsigned long memory = available_memory(); - - double projected_usage = (double)size / (double)memory; - printf("projected memory usage: %.3f\n", projected_usage); - if (projected_usage > MEMORY_USAGE) + bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT, + MEMORY_USAGE, true); + if (! fits) { // Projected memory usage is really high, so abort. return send_simple_response(response, 500, "error", diff --git a/src/auxiliary.c b/src/auxiliary.c index 6b833d80adc22a36440437496bb7fc0936e4ebb1..9773c09528bd10ef5120a9bb745b9fc733a5981e 100644 --- a/src/auxiliary.c +++ b/src/auxiliary.c @@ -111,6 +111,45 @@ unsigned long filesystem_usage(const char * path) return (s.f_blocks - s.f_bfree) * s.f_bsize; } +/** + * Check if the files on the given filesystem would fit into memory. + * @param path Path of the mounted filesystem. + * @param safety_margin Fraction (between zero and one) of free memory to + deem available for containing the files. + * @param debug Whether to print debug messages. + * @return Whether the filesystem seems to fit into memory. + */ +bool filesystem_fits_in_memory(const char * path, double safety_margin, + bool debug) +{ + // Determine the filesystem usage of the device to be encrypted. + unsigned long size = filesystem_usage(path); + if (size < 0) + { + // Something went wrong in determining the filesystem usage. + // Return false as a precaution. + if (debug) + { + printf("Determining file system usage failed (size: %lu)\n", size); + } + return false; + } + if (debug) + { + printf("file system usage: %lu bytes\n", size); + } + + // Determine the available memory. + unsigned long memory = available_memory(); + + double projected_usage = (double)size / (double)memory; + if (debug) + { + printf("projected memory usage: %.3f\n", projected_usage); + } + return (projected_usage <= safety_margin); +} + /** * Mount a filesystem; create the mount target if it doesn't exist. * @param device_path Path to the device to mount.