+#include "ask-password-api.h"
+
+static unsigned opt_tries = 0;
+static char *opt_cipher = NULL;
+static unsigned opt_size = 0;
+static char *opt_hash = NULL;
+static bool opt_readonly = false;
+static bool opt_verify = false;
+static usec_t arg_timeout = 0;
+
+static int parse_one_option(const char *option) {
+ assert(option);
+
+ /* Handled outside of this tool */
+ if (streq(option, "swap") ||
+ streq(option, "tmp") ||
+ streq(option, "noauto"))
+ return 0;
+
+ if (startswith(option, "cipher=")) {
+ char *t;
+
+ if (!(t = strdup(option+7)))
+ return -ENOMEM;
+
+ free(opt_cipher);
+ opt_cipher = t;
+
+ } else if (startswith(option, "size=")) {
+
+ if (safe_atou(option+5, &opt_size) < 0) {
+ log_error("size= parse failure, ignoring.");
+ return 0;
+ }
+
+ } else if (startswith(option, "hash=")) {
+ char *t;
+
+ if (!(t = strdup(option+5)))
+ return -ENOMEM;
+
+ free(opt_hash);
+ opt_hash = t;
+
+ } else if (startswith(option, "tries=")) {
+
+ if (safe_atou(option+6, &opt_tries) < 0) {
+ log_error("tries= parse failure, ignoring.");
+ return 0;
+ }
+
+ } else if (streq(option, "readonly"))
+ opt_readonly = true;
+ else if (streq(option, "verify"))
+ opt_verify = true;
+ else if (startswith(option, "timeout=")) {
+
+ if (parse_usec(option+8, &arg_timeout) < 0) {
+ log_error("timeout= parse failure, ignoring.");
+ return 0;
+ }
+
+ } else
+ log_error("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
+
+ return 0;
+}
+
+static int parse_options(const char *options) {
+ char *state;
+ char *w;
+ size_t l;
+
+ assert(options);
+
+ FOREACH_WORD_SEPARATOR(w, l, options, ",", state) {
+ char *o;
+ int r;
+
+ if (!(o = strndup(w, l)))
+ return -ENOMEM;
+
+ r = parse_one_option(o);
+ free(o);
+
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static void log_glue(int level, const char *msg, void *usrptr) {
+
+ log_full(level == CRYPT_LOG_ERROR ? LOG_ERR :
+ level == CRYPT_LOG_VERBOSE ? LOG_INFO :
+ level == CRYPT_LOG_DEBUG ? LOG_DEBUG :
+ LOG_NOTICE,
+ "%s", msg);
+}
+
+static int password_glue(const char *msg, char *buf, size_t length, void *usrptr) {
+ usec_t until;
+ char *password = NULL;
+ int k;
+
+ until = now(CLOCK_MONOTONIC) + (arg_timeout > 0 ? arg_timeout : 60 * USEC_PER_SEC);
+
+ if ((k = ask_password_agent(msg, "drive-harddisk", until, &password)) < 0)
+ return k;
+
+ strncpy(buf, password, length-1);
+ buf[length-1] = 0;
+
+ free(password);
+
+ return strlen(buf);
+}