/** * Flush bitmap to disk. * @return TRUE on sucess */ static gboolean flush_bitbuf(DBM *db) { DBMBIG *dbg = db->big; ssize_t w; dbg->bitwrite++; w = compat_pwrite(dbg->fd, dbg->bitbuf, BIG_BLKSIZE, OFF_DAT(dbg->bitbno)); if (BIG_BLKSIZE == w) { dbg->bitbuf_dirty = FALSE; return TRUE; } g_warning("sdbm: \"%s\": cannot flush bitmap #%ld: %s", sdbm_name(db), dbg->bitbno / BIG_BITCOUNT, -1 == w ? g_strerror(errno) : "partial write"); ioerr(db, TRUE); return FALSE; }
/** * Flush page to disk. * @return TRUE on success */ gboolean flushpag(DBM *db, char *pag, long num) { ssize_t w; g_assert(num >= 0); db->pagwrite++; w = compat_pwrite(db->pagf, pag, DBM_PBLKSIZ, OFF_PAG(num)); if (w < 0 || w != DBM_PBLKSIZ) { if (w < 0) g_warning("sdbm: \"%s\": cannot flush page #%ld: %s", sdbm_name(db), num, g_strerror(errno)); else g_warning("sdbm: \"%s\": could only flush %u bytes from page #%ld", sdbm_name(db), (unsigned) w, num); ioerr(db, TRUE); db->flush_errors++; return FALSE; } return TRUE; }
/** * Store big value in the .dat file, writing to the supplied block numbers. * * @param db the sdbm database * @param bvec start of block vector, containing block numbers * @param data start of data to write * @param len length of data to write * * @return -1 on error with errno set, 0 if OK. */ static int big_store(DBM *db, const void *bvec, const void *data, size_t len) { DBMBIG *dbg = db->big; int bcnt = bigbcnt(len); int n; const void *p; const char *q; size_t remain; g_return_val_if_fail(NULL == dbg->bitcheck, -1); if (-1 == dbg->fd && -1 == big_open(dbg)) return -1; /* * Look at the amount of consecutive block numbers we have to be able * to write into them via a single system call. */ n = bcnt; p = bvec; q = data; remain = len; while (n > 0) { size_t towrite = MIN(remain, BIG_BLKSIZE); guint32 bno = peek_be32(p); guint32 prev_bno = bno; p = const_ptr_add_offset(p, sizeof(guint32)); n--; remain = size_saturate_sub(remain, towrite); while (n > 0) { guint32 next_bno = peek_be32(p); size_t amount; if (next_bno <= prev_bno) /* Block numbers are sorted */ goto corrupted_page; if (next_bno - prev_bno != 1) break; /* Not consecutive */ prev_bno = next_bno; p = const_ptr_add_offset(p, sizeof(guint32)); amount = MIN(remain, BIG_BLKSIZE); towrite += amount; n--; remain = size_saturate_sub(remain, amount); } dbg->bigwrite++; if (-1 == compat_pwrite(dbg->fd, q, towrite, OFF_DAT(bno))) { g_warning("sdbm: \"%s\": " "could not write %lu bytes starting at data block #%u: %s", sdbm_name(db), (unsigned long) towrite, bno, g_strerror(errno)); ioerr(db, TRUE); return -1; } q += towrite; dbg->bigwrite_blk += bigblocks(towrite); g_assert(ptr_diff(q, data) <= len); } g_assert(ptr_diff(q, data) == len); return 0; corrupted_page: g_warning("sdbm: \"%s\": corrupted page: %d big data block%s not sorted", sdbm_name(db), bcnt, 1 == bcnt ? "" : "s"); ioerr(db, FALSE); errno = EFAULT; /* Data corrupted somehow (.pag file) */ return -1; }