Add crypt_last_error() API call (using crypt context).
authorMilan Broz <gmazyland@gmail.com>
Sun, 9 Oct 2011 13:45:53 +0000 (13:45 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sun, 9 Oct 2011 13:45:53 +0000 (13:45 +0000)
git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@623 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
lib/internal.h
lib/libcryptsetup.h
lib/libcryptsetup.sym
lib/setup.c
tests/api-test.c

index 4e44b8f..0414edb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 2011-10-05  Milan Broz  <mbroz@redhat.com>
        * Support Nettle 2.4 crypto backend (for ripemd160).
        * If device is not rotational, do not use Gutmann wipe method.
+       * Add crypt_last_error() API call.
 
 2011-09-22  Milan Broz  <mbroz@redhat.com>
        * Support key-slot option for luksOpen (use only explicit keyslot).
index ff51a3e..85435aa 100644 (file)
@@ -22,6 +22,7 @@
 #define SECTOR_SIZE            (1 << SECTOR_SHIFT)
 #define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
 #define DEFAULT_MEM_ALIGNMENT  4096
+#define MAX_ERROR_LENGTH       512
 
 #define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
 
index 897fd64..2fc919b 100644 (file)
@@ -882,6 +882,18 @@ int crypt_header_restore(struct crypt_device *cd,
 /**
  * Receives last reported error
  *
+ * @param cd crypt device handle
+ * @param buf buffef for message
+ * @param size size of buffer
+ *
+ * @note Note that this is old API function using global context.
+ * All error messages are reported also through log callback.
+ */
+void crypt_last_error(struct crypt_device *cd, char *buf, size_t size);
+
+/**
+ * Receives last reported error, DEPRECATED
+ *
  * @param buf buffef for message
  * @param size size of buffer
  *
index 53ccaad..a758798 100644 (file)
@@ -50,6 +50,7 @@ CRYPTSETUP_1.0 {
 
                crypt_keyslot_max;
                crypt_keyslot_status;
+               crypt_last_error;
                crypt_get_error;
                crypt_get_dir;
                crypt_set_debug_level;
index a616fc9..3550101 100644 (file)
@@ -71,11 +71,14 @@ struct crypt_device {
        void *confirm_usrptr;
        int (*password)(const char *msg, char *buf, size_t length, void *usrptr);
        void *password_usrptr;
+
+       /* last error message */
+       char error[MAX_ERROR_LENGTH];
 };
 
 /* Global error */
 /* FIXME: not thread safe, remove this later */
-static char global_error[512] = {0};
+static char global_error[MAX_ERROR_LENGTH] = {0};
 
 /* Log helper */
 static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
@@ -100,14 +103,21 @@ void crypt_log(struct crypt_device *cd, int level, const char *msg)
                _default_log(level, msg, NULL);
 }
 
-/* Set global error, ugly hack... */
-void set_global_error(const char *error)
+static void crypt_set_error(struct crypt_device *cd, const char *error)
 {
        size_t size = strlen(error);
 
-       strncpy(global_error, error, sizeof(global_error) - 2);
-       if (size < sizeof(global_error) && global_error[size - 1] == '\n')
+       /* Set global error, ugly hack... */
+       strncpy(global_error, error, MAX_ERROR_LENGTH - 2);
+       if (size < MAX_ERROR_LENGTH && global_error[size - 1] == '\n')
                global_error[size - 1] = '\0';
+
+       /* Set error string per context */
+       if (cd) {
+               strncpy(cd->error, error, MAX_ERROR_LENGTH - 2);
+               if (size < MAX_ERROR_LENGTH && cd->error[size - 1] == '\n')
+                       cd->error[size - 1] = '\0';
+       }
 }
 
 __attribute__((format(printf, 5, 6)))
@@ -131,7 +141,7 @@ void logger(struct crypt_device *cd, int level, const char *file,
 #endif
 
                if (level == CRYPT_LOG_ERROR)
-                       set_global_error(target);
+                       crypt_set_error(cd, target);
        }
 
        va_end(argp);
@@ -429,19 +439,30 @@ void crypt_set_password_callback(struct crypt_device *cd,
        cd->password_usrptr = usrptr;
 }
 
-/* Deprecated global error interface */
-void crypt_get_error(char *buf, size_t size)
+static void _get_error(char *error, char *buf, size_t size)
 {
        if (!buf || size < 1)
-               global_error[0] = '\0';
-       else if (*global_error) {
-               strncpy(buf, global_error, size - 1);
+               error[0] = '\0';
+       else if (*error) {
+               strncpy(buf, error, size - 1);
                buf[size - 1] = '\0';
-               global_error[0] = '\0';
+               error[0] = '\0';
        } else
                buf[0] = '\0';
 }
 
+void crypt_last_error(struct crypt_device *cd, char *buf, size_t size)
+{
+       if (cd)
+               return _get_error(cd->error, buf, size);
+}
+
+/* Deprecated global error interface */
+void crypt_get_error(char *buf, size_t size)
+{
+       return _get_error(global_error, buf, size);
+}
+
 const char *crypt_get_dir(void)
 {
        return dm_get_dir();
index 81e36a9..53a5717 100644 (file)
@@ -441,24 +441,24 @@ static int _setup(void)
        return 0;
 }
 
-void check_ok(int status, int line, const char *func)
+void check_ok(struct crypt_device *cd, int status, int line, const char *func)
 {
        char buf[256];
 
        if (status) {
-               crypt_get_error(buf, sizeof(buf));
+               crypt_last_error(cd, buf, sizeof(buf));
                printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
                _cleanup();
                exit(-1);
        }
 }
 
-void check_ko(int status, int line, const char *func)
+void check_ko(struct crypt_device *cd, int status, int line, const char *func)
 {
        char buf[256];
 
        memset(buf, 0, sizeof(buf));
-       crypt_get_error(buf, sizeof(buf));
+       crypt_last_error(cd, buf, sizeof(buf));
        if (status >= 0) {
                printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
                _cleanup();
@@ -483,11 +483,13 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch
                        printf(" [%s,%s:%d] %s\n", msg, func, line, tst);
        }
 }
+
+/* crypt_device context must be "cd" to parse error properly here */
 #define OK_(x)         do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \
-                            check_ok((x), __LINE__, __FUNCTION__); \
+                            check_ok(cd, (x), __LINE__, __FUNCTION__); \
                        } while(0)
 #define FAIL_(x, y)    do { xlog("(fail)   ", #x, __FUNCTION__, __LINE__, y); \
-                            check_ko((x), __LINE__, __FUNCTION__); \
+                            check_ko(cd, (x), __LINE__, __FUNCTION__); \
                        } while(0)
 #define EQ_(x, y)      do { xlog("(equal)  ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
                             if ((x) != (y)) check_equal(__LINE__, __FUNCTION__); \
@@ -495,11 +497,9 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch
 
 #define RUN_(x, y)             do { printf("%s: %s\n", #x, (y)); x(); } while (0)
 
-// NEW API tests
-
 static void AddDevicePlain(void)
 {
-       struct crypt_device *cd, *cd2;
+       struct crypt_device *cd;
        struct crypt_params_plain params = {
                .hash = "sha1",
                .skip = 0,
@@ -654,11 +654,12 @@ static void AddDevicePlain(void)
        OK_(crypt_init(&cd,DEVICE_1));
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
-       FAIL_(crypt_init_by_name_and_header(&cd2, CDEVICE_1, H_DEVICE),"can't init plain device by header device");
-       OK_(crypt_init_by_name(&cd2,CDEVICE_1));
-       OK_(crypt_deactivate(cd,CDEVICE_1));
        crypt_free(cd);
-       crypt_free(cd2);
+
+       FAIL_(crypt_init_by_name_and_header(&cd, CDEVICE_1, H_DEVICE),"can't init plain device by header device");
+       OK_(crypt_init_by_name(&cd, CDEVICE_1));
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+       crypt_free(cd);
 
        OK_(crypt_init(&cd,DEVICE_1));
        OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
@@ -812,6 +813,7 @@ static void CallbacksTest(void)
        char *cipher = "aes";
        char *cipher_mode = "cbc-essiv:sha256";
        char *passphrase = PASSPHRASE;
+       char buf1[256] = {0}, buf2[256] = {0};
 
        OK_(crypt_init(&cd, DEVICE_1));
        crypt_set_log_callback(cd, &new_log, NULL);
@@ -833,6 +835,22 @@ static void CallbacksTest(void)
        EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
+       // Check error reporting.
+       // This must fail and create error message
+       crypt_deactivate(cd, CDEVICE_1);
+
+       // Here context must be the same
+       crypt_get_error(buf1, sizeof(buf1));
+       crypt_last_error(cd, buf2, sizeof(buf2));
+       OK_(!*buf1);
+       OK_(!*buf2);
+       OK_(strcmp(buf1, buf2));
+
+       crypt_get_error(buf1, sizeof(buf1));
+       crypt_last_error(cd, buf2, sizeof(buf2));
+       OK_(*buf1);
+       OK_(*buf2);
+
        crypt_free(cd);
 }