summaryrefslogtreecommitdiff
path: root/trust/token.c
diff options
context:
space:
mode:
Diffstat (limited to 'trust/token.c')
-rw-r--r--trust/token.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/trust/token.c b/trust/token.c
index f48f66b..c5991df 100644
--- a/trust/token.c
+++ b/trust/token.c
@@ -65,6 +65,9 @@ struct _p11_token {
char *label;
CK_SLOT_ID slot;
int loaded;
+
+ bool checked_writable;
+ bool is_writable;
};
static int
@@ -314,3 +317,47 @@ p11_token_index (p11_token *token)
return_val_if_fail (token != NULL, NULL);
return token->index;
}
+
+static bool
+check_writable_directory (const char *path)
+{
+ struct stat sb;
+ char *parent;
+ bool ret;
+
+ if (access (path, W_OK) == 0)
+ return stat (path, &sb) == 0 && S_ISDIR (sb.st_mode);
+
+ switch (errno) {
+ case EACCES:
+ return false;
+ case ENOENT:
+ parent = p11_path_parent (path);
+ if (parent == NULL)
+ ret = false;
+ else
+ ret = check_writable_directory (parent);
+ free (parent);
+ return ret;
+ default:
+ p11_message ("couldn't access: %s: %s", path, strerror (errno));
+ return false;
+ }
+}
+
+bool
+p11_token_is_writable (p11_token *token)
+{
+ /*
+ * This function attempts to determine whether a later write
+ * to this token will succeed so we can setup the appropriate
+ * token flags. Yes, it is racy, but that's inherent to the problem.
+ */
+
+ if (!token->checked_writable) {
+ token->is_writable = check_writable_directory (token->path);
+ token->checked_writable = true;
+ }
+
+ return token->is_writable;
+}