• [PATCH] Factor out common code for reloading database files (2/2)

    From Simon Richter@1:229/2 to All on Fri May 5 21:10:02 2023
    [continued from previous message]

    + file = dpkg_db_reopen(&info, statoverridename, &unchanged);

    - file = fopen(statoverridename, "r");
    - if (!file) {
    - if (errno != ENOENT)
    - ohshite(_("failed to open statoverride file"));
    - } else {
    - setcloexec(fileno(file), statoverridename);
    -
    - if (fstat(fileno(file), &sb_next))
    - ohshite(_("failed to fstat statoverride file"));
    -
    - /*
    - * We need to keep the database file open so that the
    - * filesystem cannot reuse the inode number (f.ex. during
    - * multiple dpkg-statoverride invocations in a maintainer
    - * script), otherwise the following check might turn true,
    - * and we would skip reloading a modified database.
    - */
    - if (file_prev &&
    - sb_prev.st_dev == sb_next.st_dev &&
    - sb_prev.st_ino == sb_next.st_ino) {
    - fclose(file);
    - onerr_abort--;
    - debug(dbg_general, "%s: same, skipping", __func__);
    - return;
    - }
    - sb_prev = sb_next;
    - }
    - if (file_prev)
    - fclose(file_prev);
    - file_prev = file;
    + if (unchanged)
    + return;
    +
    + onerr_abort++;

    /* Reset statoverride information. */
    iter = fsys_hash_iter_new();
    @@ -171,15 +143,15 @@ ensure_statoverrides(enum statdb_parse_flags flags)

    /* If the statoverride list is empty we don't need to bother
    * reading it. */
    - if (!sb_next.st_size) {
    + if (!info.sb.st_size) {
    onerr_abort--;
    return;
    }

    - loaded_list = m_malloc(sb_next.st_size);
    - loaded_list_end = loaded_list + sb_next.st_size;
    + loaded_list = m_malloc(info.sb.st_size);
    + loaded_list_end = loaded_list + info.sb.st_size;

    - if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0)
    + if (fd_read(fileno(file), loaded_list, info.sb.st_size) < 0)
    ohshite(_("reading statoverride file '%.250s'"), statoverridename);

    thisline = loaded_list;
    diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
    index 61f220506..4d602cb00 100644
    --- a/lib/dpkg/dpkg-db.h
    +++ b/lib/dpkg/dpkg-db.h
    @@ -24,6 +24,7 @@
    #define LIBDPKG_DPKG_DB_H

    #include <sys/types.h>
    +#include <sys/stat.h>

    #include <stdbool.h>
    #include <stdio.h>
    @@ -259,6 +260,18 @@ const char *dpkg_db_set_dir(const char *dir);
    const char *dpkg_db_get_dir(void);
    char *dpkg_db_get_path(const char *pathpart);

    +/*** from db-fsys-common.c ***/
    +
    +struct dbinfo {
    + FILE *file;
    + struct stat sb;
    +};
    +
    +FILE *dpkg_db_reopen(
    + struct dbinfo *info,
    + char const *filename,
    + bool *unchanged);
    +
    #include <dpkg/atomic-file.h>

    /*** from dbmodify.c ***/
    --
    2.39.2

    --- SoupGate-Win32 v1.05
    * Origin: you cannot sedate... all the things you hate (1:229/2)
  • From Simon Richter@1:229/2 to All on Sun Mar 17 00:40:02 2024
    [continued from previous message]

    statoverridename = dpkg_db_get_path(STATOVERRIDEFILE);

    - onerr_abort++;
    + file = dpkg_db_reopen(&dbi, statoverridename, &unchanged);

    - file = fopen(statoverridename, "r");
    - if (!file) {
    - if (errno != ENOENT)
    - ohshite(_("failed to open statoverride file"));
    - } else {
    - setcloexec(fileno(file), statoverridename);
    -
    - if (fstat(fileno(file), &sb_next))
    - ohshite(_("failed to fstat statoverride file"));
    -
    - /*
    - * We need to keep the database file open so that the
    - * filesystem cannot reuse the inode number (f.ex. during
    - * multiple dpkg-statoverride invocations in a maintainer
    - * script), otherwise the following check might turn true,
    - * and we would skip reloading a modified database.
    - */
    - if (file_prev &&
    - sb_prev.st_dev == sb_next.st_dev &&
    - sb_prev.st_ino == sb_next.st_ino) {
    - fclose(file);
    - onerr_abort--;
    - debug(dbg_general, "%s: same, skipping", __func__);
    - return;
    - }
    - sb_prev = sb_next;
    - }
    - if (file_prev)
    - fclose(file_prev);
    - file_prev = file;
    + if (unchanged)
    + return;
    +
    + onerr_abort++;

    /* Reset statoverride information. */
    iter = fsys_hash_iter_new();
    @@ -171,15 +143,15 @@ ensure_statoverrides(enum statdb_parse_flags flags)

    /* If the statoverride list is empty we don't need to bother
    * reading it. */
    - if (!sb_next.st_size) {
    + if (!dbi.sb.st_size) {
    onerr_abort--;
    return;
    }

    - loaded_list = m_malloc(sb_next.st_size);
    - loaded_list_end = loaded_list + sb_next.st_size;
    + loaded_list = m_malloc(dbi.sb.st_size);
    + loaded_list_end = loaded_list + dbi.sb.st_size;

    - if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0)
    + if (fd_read(fileno(file), loaded_list, dbi.sb.st_size) < 0)
    ohshite(_("reading statoverride file '%.250s'"), statoverridename);

    thisline = loaded_list;
    diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
    index 61f220506..4d602cb00 100644
    --- a/lib/dpkg/dpkg-db.h
    +++ b/lib/dpkg/dpkg-db.h
    @@ -24,6 +24,7 @@
    #define LIBDPKG_DPKG_DB_H

    #include <sys/types.h>
    +#include <sys/stat.h>

    #include <stdbool.h>
    #include <stdio.h>
    @@ -259,6 +260,18 @@ const char *dpkg_db_set_dir(const char *dir);
    const char *dpkg_db_get_dir(void);
    char *dpkg_db_get_path(const char *pathpart);

    +/*** from db-fsys-common.c ***/
    +
    +struct dbinfo {
    + FILE *file;
    + struct stat sb;
    +};
    +
    +FILE *dpkg_db_reopen(
    + struct dbinfo *info,
    + char const *filename,
    + bool *unchanged);
    +
    #include <dpkg/atomic-file.h>

    /*** from dbmodify.c ***/
    --
    2.39.2

    --- SoupGate-Win32 v1.05
    * Origin: you cannot sedate... all the things you hate (1:229/2)
  • From Guillem Jover@1:229/2 to All on Sun Mar 17 17:30:01 2024
    [continued from previous message]

    +#include <sys/types.h>
    +#include <sys/stat.h>
    +
    +#include <errno.h>
    +
    +#include <dpkg/dpkg.h>
    +#include <dpkg/dpkg-db.h>
    +#include <dpkg/db-fsys.h>
    +#include <dpkg/i18n.h>
    +#include <dpkg/debug.h>
    +
    +enum dpkg_db_error
    +dpkg_db_reopen(struct dpkg_db *db)
    +{
    + struct stat st_next;
    + FILE *file_next;
    +
    + if (db->pathname == NULL)
    + db->pathname = dpkg_db_get_path(db->name);
    +
    + onerr_abort++;
    +
    + file_next = fopen(db->pathname, "r");
    + if (!file_next) {
    + if (errno != ENOENT)
    + ohshite(_("cannot open %s file"), db->pathname);
    + } else {
    + setcloexec(fileno(file_next), db->pathname);
    +
    + if (fstat(fileno(file_next), &st_next))
    + ohshite(_("cannot get %s file metadata"), db->pathname);
    +
    + /*
    + * We need to keep the database file open so that the
    + * filesystem cannot reuse the inode number (f.ex. during
    + * multiple dpkg-divert invocations in a maintainer script),
    + * otherwise the following check might turn true, and we
    + * would skip reloading a modified database.
    + */
    + if (db->file &&
    + db->st.st_dev == st_next.st_dev &&
    + db->st.st_ino == st_next.st_ino) {
    + fclose(file_next);
    + onerr_abort--;
    +
    + debug(dbg_general, "%s: unchanged %s, skipping",
    + __func__, db->pathname);
    + return DPKG_DB_SAME;
    + }
    + db->st = st_next;
    + }
    + if (db->file)
    + fclose(db->file);
    + db->file = file_next;
    +
    + onerr_abort--;
    +
    + if (db->file) {
    + debug(dbg_general, "%s: new %s, (re)loading",
    + __func__, db->pathname);
    + return DPKG_DB_LOAD;
    + } else {
    + debug(dbg_general, "%s: missing %s, resetting",
    + __func__, db->pathname);
    + return DPKG_DB_NONE;
    + }
    +}
    diff --git a/lib/dpkg/db-fsys-override.c b/lib/dpkg/db-fsys-override.c
    index b74f6cbc2..120bc3dd8 100644
    --- a/lib/dpkg/db-fsys-override.c
    +++ b/lib/dpkg/db-fsys-override.c
    @@ -24,7 +24,6 @@
    #include <compat.h>

    #include <sys/types.h>
    -#include <sys/stat.h>

    #include <errno.h>
    #include <string.h>
    @@ -41,8 +40,6 @@
    #include <dpkg/debug.h>
    #include <dpkg/db-fsys.h>

    -static char *statoverridename;
    -
    uid_t
    statdb_parse_uid(const char *str)
    {
    @@ -111,76 +108,44 @@ statdb_parse_mode(const char *str)
    void
    ensure_statoverrides(enum statdb_parse_flags flags)
    {
    - static struct stat sb_prev;
    - struct stat sb_next;
    - static FILE *file_prev;
    - FILE *file;
    + static struct dpkg_db db = {
    + .name = STATOVERRIDEFILE,
    + };
    + enum dpkg_db_error rc;
    char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr;
    struct file_stat *fso;
    struct fsys_namenode *fnn;
    struct fsys_hash_iter *iter;

    - if (statoverridename == NULL)
    - statoverridename = dpkg_db_get_path(STATOVERRIDEFILE);
    + rc = dpkg_db_reopen(&db);
    + if (rc == DPKG_DB_SAME)
    + return;

    onerr_abort++;