]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/io.c
ttxml: removed cruft from tests
[ccan] / ccan / tdb2 / io.c
index 3648505f12c37d688337e86ae70883558d7e01e5..b4a6f0beae11160ac37ab7987d957c81e92612ac 100644 (file)
@@ -81,8 +81,8 @@ void tdb_mmap(struct tdb_context *tdb)
 
    If probe is true, len being too large isn't a failure.
 */
-static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
-                             bool probe)
+static enum TDB_ERROR tdb_oob(struct tdb_context *tdb,
+                             tdb_off_t off, tdb_len_t len, bool probe)
 {
        struct stat st;
        enum TDB_ERROR ecode;
@@ -92,7 +92,16 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
               || (tdb->flags & TDB_NOLOCK)
               || tdb_has_expansion_lock(tdb));
 
-       if (len <= tdb->file->map_size)
+       if (len + off < len) {
+               if (probe)
+                       return TDB_SUCCESS;
+
+               return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                 "tdb_oob off %llu len %llu wrap\n",
+                                 (long long)off, (long long)len);
+       }
+
+       if (len + off <= tdb->file->map_size)
                return TDB_SUCCESS;
        if (tdb->flags & TDB_INTERNAL) {
                if (probe)
@@ -101,7 +110,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
                tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
                           "tdb_oob len %lld beyond internal"
                           " malloc size %lld",
-                          (long long)len,
+                          (long long)(off + len),
                           (long long)tdb->file->map_size);
                return TDB_ERR_IO;
        }
@@ -120,13 +129,13 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
 
        tdb_unlock_expand(tdb, F_RDLCK);
 
-       if (st.st_size < (size_t)len) {
+       if (st.st_size < off + len) {
                if (probe)
                        return TDB_SUCCESS;
 
                tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-                          "tdb_oob len %zu beyond eof at %zu",
-                          (size_t)len, st.st_size);
+                          "tdb_oob len %llu beyond eof at %zu",
+                          (long long)(off + len), st.st_size);
                return TDB_ERR_IO;
        }
 
@@ -162,7 +171,7 @@ uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
        val = tdb_access_read(tdb, base + start * sizeof(tdb_off_t),
                              (end - start) * sizeof(tdb_off_t), false);
        if (TDB_PTR_IS_ERR(val)) {
-               return TDB_PTR_ERR(val);
+               return TDB_ERR_TO_OFF(TDB_PTR_ERR(val));
        }
 
        for (i = 0; i < (end - start); i++) {
@@ -183,7 +192,7 @@ uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
        /* Zero vs non-zero is the same unconverted: minor optimization. */
        val = tdb_access_read(tdb, off, num * sizeof(tdb_off_t), false);
        if (TDB_PTR_IS_ERR(val)) {
-               return TDB_PTR_ERR(val);
+               return TDB_ERR_TO_OFF(TDB_PTR_ERR(val));
        }
 
        for (i = 0; i < num; i++) {
@@ -229,7 +238,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
                tdb_off_t *p = tdb->tdb2.io->direct(tdb, off, sizeof(*p),
                                                    false);
                if (TDB_PTR_IS_ERR(p)) {
-                       return TDB_PTR_ERR(p);
+                       return TDB_ERR_TO_OFF(TDB_PTR_ERR(p));
                }
                if (p)
                        return *p;
@@ -237,7 +246,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 
        ecode = tdb_read_convert(tdb, off, &ret, sizeof(ret));
        if (ecode != TDB_SUCCESS) {
-               return ecode;
+               return TDB_ERR_TO_OFF(ecode);
        }
        return ret;
 }
@@ -253,7 +262,7 @@ static enum TDB_ERROR tdb_write(struct tdb_context *tdb, tdb_off_t off,
                                  "Write to read-only database");
        }
 
-       ecode = tdb->tdb2.io->oob(tdb, off + len, false);
+       ecode = tdb->tdb2.io->oob(tdb, off, len, false);
        if (ecode != TDB_SUCCESS) {
                return ecode;
        }
@@ -283,7 +292,7 @@ static enum TDB_ERROR tdb_read(struct tdb_context *tdb, tdb_off_t off,
 {
        enum TDB_ERROR ecode;
 
-       ecode = tdb->tdb2.io->oob(tdb, off + len, false);
+       ecode = tdb->tdb2.io->oob(tdb, off, len, false);
        if (ecode != TDB_SUCCESS) {
                return ecode;
        }
@@ -574,7 +583,7 @@ static void *tdb_direct(struct tdb_context *tdb, tdb_off_t off, size_t len,
        if (unlikely(!tdb->file->map_ptr))
                return NULL;
 
-       ecode = tdb_oob(tdb, off + len, false);
+       ecode = tdb_oob(tdb, off, len, false);
        if (unlikely(ecode != TDB_SUCCESS))
                return TDB_ERR_PTR(ecode);
        return (char *)tdb->file->map_ptr + off;