aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeebs <seebs@seebs.net>2018-09-20 13:35:28 -0500
committerSeebs <seebs@seebs.net>2018-09-20 13:35:28 -0500
commitca86e30df5e6a9f51af677af8691c86a3f894555 (patch)
tree913cd9f0ee0dba145ad37f5f2f9a6885bb31fa48
parentfddbe854c9db058d5a05830d3bcdd4233d95ee2e (diff)
downloadpseudo-ca86e30df5e6a9f51af677af8691c86a3f894555.tar.gz
pseudo-ca86e30df5e6a9f51af677af8691c86a3f894555.tar.bz2
pseudo-ca86e30df5e6a9f51af677af8691c86a3f894555.zip
attempt to handle large inode values
So ino_t is uint64_t, sqlite field types are magical and erratic and if a value doesn't fit inside signed int64, it gets converted to float64. of course. This means that the top half of the inode range produces invalid-ish values, because a 64-bit double is typically 53 bits of mantissa, so a value around 2^64 will convert to a float64 value which is going to compare equal to at least 2^10 other integer values if they were also converted to float64. Which makes weird problems.
-rw-r--r--ChangeLog.txt4
-rw-r--r--pseudo_db.c72
2 files changed, 52 insertions, 24 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index d6e3fca..d2a8862 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,7 @@
+2018-09-20:
+ * (seebs) coerce inodes to signed int64_t range when shoving
+ them into sqlite.
+
2018-04-13:
* (seebs) Reduce spamminess of path mismatches.
Don't log path mismatches with multiple links unless you've
diff --git a/pseudo_db.c b/pseudo_db.c
index a9e294b..d5dca39 100644
--- a/pseudo_db.c
+++ b/pseudo_db.c
@@ -370,6 +370,30 @@ dberr(sqlite3 *db, char *fmt, ...) {
}
}
+/* sqlite3 supports only signed integers, thus, the highest positive
+ * value is 2^63-1. some filesystems with 64-bit ino_t will produce
+ * ino_t values in the 2^63..2^64-1 range. we convert those into
+ * the value you'd get treating the 2^63 bit as a sign bit, so sqlite
+ * doesn't convert them into floats, because the float type can't
+ * represent values accurately in this range, which can result in
+ * erroneous matches, etcetera.
+ *
+ * note, when reading the values back out, the conversion does the
+ * right thing. e.g., if the inode number had been 2^63 exactly,
+ * it will convert to -(2^63). that, converted to unsigned, will
+ * convert back to 2^63 exactly, etcetera.
+ *
+ * so far as i know, ino_t is always unsigned. we don't care about
+ * the 32-bit inode case; sqlite can represent those just fine.
+ */
+static int64_t
+signed_ino(ino_t ino) {
+ if (ino > (uint64_t) INT64_MAX) {
+ return (int64_t) (ino + INT64_MIN) + INT64_MIN;
+ }
+ return (int64_t) ino;
+}
+
#ifdef USE_MEMORY_DB
static void
@@ -782,7 +806,7 @@ pdb_log_traits(pseudo_query_t *traits) {
e->gid = trait->data.ivalue;
break;
case PSQF_INODE:
- e->ino = trait->data.ivalue;
+ e->ino = (ino_t) trait->data.ivalue;
break;
case PSQF_MODE:
e->mode = trait->data.ivalue;
@@ -875,7 +899,7 @@ pdb_log_entry(log_entry *e) {
sqlite3_bind_int(insert, field++, e->client);
sqlite3_bind_int(insert, field++, e->dev);
sqlite3_bind_int(insert, field++, e->gid);
- sqlite3_bind_int64(insert, field++, e->ino);
+ sqlite3_bind_int64(insert, field++, signed_ino(e->ino));
sqlite3_bind_int(insert, field++, e->mode);
if (e->path) {
sqlite3_bind_text(insert, field++, e->path, -1, SQLITE_STATIC);
@@ -969,7 +993,7 @@ pdb_log_msg(pseudo_sev_t severity, pseudo_msg_t *msg, const char *program, const
sqlite3_bind_int(insert, field++, msg->client);
sqlite3_bind_int(insert, field++, msg->dev);
sqlite3_bind_int(insert, field++, msg->gid);
- sqlite3_bind_int64(insert, field++, msg->ino);
+ sqlite3_bind_int64(insert, field++, signed_ino(msg->ino));
sqlite3_bind_int(insert, field++, msg->mode);
if (msg->pathlen) {
sqlite3_bind_text(insert, field++, msg->path, -1, SQLITE_STATIC);
@@ -1376,7 +1400,7 @@ pdb_history_entry(log_history h) {
l->gid = sqlite3_column_int64(h->stmt, column++);
break;
case PSQF_INODE:
- l->ino = sqlite3_column_int64(h->stmt, column++);
+ l->ino = (ino_t) sqlite3_column_int64(h->stmt, column++);
break;
case PSQF_MODE:
l->mode = sqlite3_column_int64(h->stmt, column++);
@@ -1512,9 +1536,9 @@ pdb_clear_xattrs(pseudo_msg_t *msg) {
}
}
sqlite3_bind_int(delete, 1, msg->dev);
- sqlite3_bind_int(delete, 2, msg->ino);
+ sqlite3_bind_int(delete, 2, signed_ino(msg->ino));
sqlite3_bind_int(delete, 3, msg->dev);
- sqlite3_bind_int(delete, 4, msg->ino);
+ sqlite3_bind_int(delete, 4, signed_ino(msg->ino));
rc = sqlite3_step(delete);
if (rc != SQLITE_DONE) {
dberr(file_db, "delete of unused xattrs may have failed");
@@ -1549,9 +1573,9 @@ pdb_copy_xattrs(pseudo_msg_t *oldmsg, pseudo_msg_t *msg) {
}
}
sqlite3_bind_int(copy, 1, msg->dev);
- sqlite3_bind_int(copy, 2, msg->ino);
+ sqlite3_bind_int(copy, 2, signed_ino(msg->ino));
sqlite3_bind_int(copy, 3, oldmsg->dev);
- sqlite3_bind_int(copy, 4, oldmsg->ino);
+ sqlite3_bind_int(copy, 4, signed_ino(oldmsg->ino));
rc = sqlite3_step(copy);
if (rc != SQLITE_DONE) {
dberr(file_db, "copy of xattrs may have failed");
@@ -1581,7 +1605,7 @@ pdb_check_xattrs(pseudo_msg_t *msg) {
}
int existing;
sqlite3_bind_int(scan, 1, msg->dev);
- sqlite3_bind_int(scan, 2, msg->ino);
+ sqlite3_bind_int(scan, 2, signed_ino(msg->ino));
rc = sqlite3_step(scan);
if (rc == SQLITE_ROW) {
existing = (int) sqlite3_column_int64(scan, 0);
@@ -1635,7 +1659,7 @@ pdb_link_file(pseudo_msg_t *msg) {
sqlite3_bind_text(insert, 1, "NAMELESS FILE", -1, SQLITE_STATIC);
}
sqlite3_bind_int(insert, 2, msg->dev);
- sqlite3_bind_int64(insert, 3, msg->ino);
+ sqlite3_bind_int64(insert, 3, signed_ino(msg->ino));
sqlite3_bind_int(insert, 4, msg->uid);
sqlite3_bind_int(insert, 5, msg->gid);
sqlite3_bind_int(insert, 6, msg->mode);
@@ -1676,7 +1700,7 @@ pdb_unlink_file_dev(pseudo_msg_t *msg) {
return 1;
}
sqlite3_bind_int(sql_delete, 1, msg->dev);
- sqlite3_bind_int64(sql_delete, 2, msg->ino);
+ sqlite3_bind_int64(sql_delete, 2, signed_ino(msg->ino));
file_db_dirty = 1;
rc = sqlite3_step(sql_delete);
if (rc != SQLITE_DONE) {
@@ -2168,7 +2192,7 @@ pdb_update_inode(pseudo_msg_t *msg) {
pdb_copy_xattrs(oldmsg, msg);
}
sqlite3_bind_int(update, 1, msg->dev);
- sqlite3_bind_int64(update, 2, msg->ino);
+ sqlite3_bind_int64(update, 2, signed_ino(msg->ino));
rc = sqlite3_bind_text(update, 3, msg->path, -1, SQLITE_STATIC);
if (rc) {
/* msg->path can never be null, and if msg didn't
@@ -2225,7 +2249,7 @@ pdb_update_file(pseudo_msg_t *msg) {
sqlite3_bind_int(update, 3, msg->mode);
sqlite3_bind_int(update, 4, msg->rdev);
sqlite3_bind_int(update, 5, msg->dev);
- sqlite3_bind_int64(update, 6, msg->ino);
+ sqlite3_bind_int64(update, 6, signed_ino(msg->ino));
file_db_dirty = 1;
rc = sqlite3_step(update);
@@ -2266,7 +2290,7 @@ pdb_find_file_exact(pseudo_msg_t *msg) {
dberr(file_db, "error binding %s to select", msg->pathlen ? msg->path : "<nil>");
}
sqlite3_bind_int(select, 2, msg->dev);
- sqlite3_bind_int64(select, 3, msg->ino);
+ sqlite3_bind_int64(select, 3, signed_ino(msg->ino));
rc = sqlite3_step(select);
switch (rc) {
case SQLITE_ROW:
@@ -2325,7 +2349,7 @@ pdb_find_file_path(pseudo_msg_t *msg) {
switch (rc) {
case SQLITE_ROW:
msg->dev = sqlite3_column_int64(select, 2);
- msg->ino = sqlite3_column_int64(select, 3);
+ msg->ino = (ino_t) sqlite3_column_int64(select, 3);
msg->uid = sqlite3_column_int64(select, 4);
msg->gid = sqlite3_column_int64(select, 5);
msg->mode = sqlite3_column_int64(select, 6);
@@ -2370,7 +2394,7 @@ pdb_get_file_path(pseudo_msg_t *msg) {
return 0;
}
sqlite3_bind_int(select, 1, msg->dev);
- sqlite3_bind_int64(select, 2, msg->ino);
+ sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
rc = sqlite3_step(select);
switch (rc) {
case SQLITE_ROW:
@@ -2419,7 +2443,7 @@ pdb_find_file_dev(pseudo_msg_t *msg, char **path) {
return 1;
}
sqlite3_bind_int(select, 1, msg->dev);
- sqlite3_bind_int64(select, 2, msg->ino);
+ sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
rc = sqlite3_step(select);
switch (rc) {
case SQLITE_ROW:
@@ -2471,7 +2495,7 @@ pdb_get_xattr(pseudo_msg_t *msg, char **value, size_t *len) {
}
pseudo_debug(PDBGF_XATTR, "requested xattr named '%s' for ino %lld\n", *value, (long long) msg->ino);
sqlite3_bind_int(select, 1, msg->dev);
- sqlite3_bind_int(select, 2, msg->ino);
+ sqlite3_bind_int(select, 2, signed_ino(msg->ino));
rc = sqlite3_bind_text(select, 3, *value, -1, SQLITE_STATIC);
if (rc) {
dberr(file_db, "couldn't bind xattr name to SELECT.");
@@ -2533,7 +2557,7 @@ pdb_list_xattr(pseudo_msg_t *msg, char **value, size_t *len) {
}
}
sqlite3_bind_int(select, 1, msg->dev);
- sqlite3_bind_int(select, 2, msg->ino);
+ sqlite3_bind_int(select, 2, signed_ino(msg->ino));
do {
rc = sqlite3_step(select);
if (rc == SQLITE_ROW) {
@@ -2587,7 +2611,7 @@ pdb_remove_xattr(pseudo_msg_t *msg, char *value, size_t len) {
}
}
sqlite3_bind_int(delete, 1, msg->dev);
- sqlite3_bind_int(delete, 2, msg->ino);
+ sqlite3_bind_int(delete, 2, signed_ino(msg->ino));
rc = sqlite3_bind_text(delete, 3, value, len, SQLITE_STATIC);
if (rc) {
dberr(file_db, "couldn't bind xattr name to DELETE.");
@@ -2628,7 +2652,7 @@ pdb_set_xattr(pseudo_msg_t *msg, char *value, size_t len, int flags) {
}
}
sqlite3_bind_int(select, 1, msg->dev);
- sqlite3_bind_int(select, 2, msg->ino);
+ sqlite3_bind_int(select, 2, signed_ino(msg->ino));
rc = sqlite3_bind_text(select, 3, value, -1, SQLITE_STATIC);
if (rc) {
dberr(file_db, "couldn't bind xattr name to SELECT.");
@@ -2697,7 +2721,7 @@ pdb_set_xattr(pseudo_msg_t *msg, char *value, size_t len, int flags) {
}
}
sqlite3_bind_int64(insert, 1, msg->dev);
- sqlite3_bind_int64(insert, 2, msg->ino);
+ sqlite3_bind_int64(insert, 2, signed_ino(msg->ino));
rc = sqlite3_bind_text(insert, 3, vname, -1, SQLITE_STATIC);
if (rc) {
dberr(file_db, "couldn't bind xattr name to INSERT statement");
@@ -2743,7 +2767,7 @@ pdb_find_file_ino(pseudo_msg_t *msg) {
if (!msg) {
return 1;
}
- sqlite3_bind_int64(select, 1, msg->ino);
+ sqlite3_bind_int64(select, 1, signed_ino(msg->ino));
rc = sqlite3_step(select);
switch (rc) {
case SQLITE_ROW:
@@ -2818,7 +2842,7 @@ pdb_file(pdb_file_list l) {
}
pseudo_debug(PDBGF_DB, "pdb_file: '%s'\n", s ? (const char *) s : "<nil>");
m->dev = sqlite3_column_int64(l->stmt, column++);
- m->ino = sqlite3_column_int64(l->stmt, column++);
+ m->ino = (ino_t) sqlite3_column_int64(l->stmt, column++);
m->uid = sqlite3_column_int64(l->stmt, column++);
m->gid = sqlite3_column_int64(l->stmt, column++);
m->mode = sqlite3_column_int64(l->stmt, column++);