backup.c
1 /*- 2 * Copyright (c) 2011-2020 Baptiste Daroussin <bapt@FreeBSD.org> 3 * Copyright (c) 2012 Matthew Seaman <matthew@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer 11 * in this position and unchanged. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <assert.h> 29 #include <fcntl.h> 30 #include <libgen.h> 31 #include <string.h> 32 #include <errno.h> 33 34 #include "pkg.h" 35 #include "private/event.h" 36 #include "private/pkg.h" 37 #include "private/pkgdb.h" 38 39 #include <bsd_compat.h> 40 41 /* Number of pages to copy per call to sqlite3_backup_step() 42 Default page size is 1024 bytes on Unix */ 43 #define NPAGES 4 44 45 static int 46 ps_cb(void *ps, int ncols, char **coltext, __unused char **colnames) 47 { 48 /* We should have exactly one row and one column of output */ 49 if (ncols != 1) 50 return (-1); /* ABORT! */ 51 52 *(off_t *)ps = strtoll(coltext[0], NULL, 10); 53 54 return (0); 55 } 56 57 static int 58 copy_database(sqlite3 *src, sqlite3 *dst) 59 { 60 sqlite3_backup *b; 61 char *errmsg; 62 off_t total; 63 off_t done; 64 off_t page_size; 65 int ret; 66 67 assert(src != NULL); 68 assert(dst != NULL); 69 70 ret = sqlite3_exec(dst, "PRAGMA main.locking_mode=EXCLUSIVE;" 71 "BEGIN IMMEDIATE;COMMIT;", NULL, NULL, &errmsg); 72 if (ret != SQLITE_OK) 73 goto out_error; 74 75 ret = sqlite3_exec(dst, "PRAGMA page_size", ps_cb, &page_size, &errmsg); 76 if (ret != SQLITE_OK) 77 goto out_error; 78 79 b = sqlite3_backup_init(dst, "main", src, "main"); 80 81 pkg_emit_progress_start(NULL); 82 do { 83 ret = sqlite3_backup_step(b, NPAGES); 84 total = sqlite3_backup_pagecount(b); 85 done = total - sqlite3_backup_remaining(b); 86 pkg_emit_progress_tick(done, total); 87 88 if (ret != SQLITE_OK && ret != SQLITE_DONE ) { 89 if (ret == SQLITE_BUSY) { 90 sqlite3_sleep(250); 91 } else { 92 ERROR_SQLITE(dst, "backup step"); 93 break; 94 } 95 } 96 } while(done < total); 97 98 ret = sqlite3_backup_finish(b); 99 pkg_emit_progress_tick(total, total); 100 101 sqlite3_exec(dst, "PRAGMA main.locking_mode=NORMAL;" 102 "BEGIN IMMEDIATE;COMMIT;", NULL, NULL, &errmsg); 103 104 if (ret == SQLITE_OK) 105 return (EPKG_OK); 106 107 out_error: 108 pkg_emit_error("sqlite error -- %s", errmsg); 109 sqlite3_free(errmsg); 110 return (EPKG_FATAL); 111 } 112 113 int 114 pkgdb_dump(struct pkgdb *db, const char *dest) 115 { 116 sqlite3 *backup; 117 int ret; 118 int destdbfd; 119 int savedfd; 120 char *dup, *dir; 121 122 dup = xstrdup(dest); 123 dir = get_dirname(dup); 124 destdbfd = open(dir, O_DIRECTORY|O_CLOEXEC); 125 if (destdbfd == -1) 126 pkg_fatal_errno("Unable to access '%s'", dir); 127 128 savedfd = pkg_get_dbdirfd(); 129 ctx.pkg_dbdirfd = destdbfd; 130 ret = sqlite3_open(dest, &backup); 131 free(dup); 132 free(dir); 133 134 if (ret != SQLITE_OK) { 135 ERROR_SQLITE(backup, "sqlite3_open"); 136 sqlite3_close(backup); 137 return (EPKG_FATAL); 138 } 139 140 pkg_emit_backup(); 141 ret = copy_database(db->sqlite, backup); 142 143 sqlite3_close(backup); 144 ctx.pkg_dbdirfd = savedfd; 145 close(savedfd); 146 147 return (ret); 148 } 149 150 int 151 pkgdb_load(struct pkgdb *db, const char *src) 152 { 153 sqlite3 *restore; 154 int ret; 155 156 if (faccessat(AT_FDCWD, src, R_OK, AT_EACCESS)) 157 pkg_fatal_errno("Unable to access '%s'", src); 158 159 ret = sqlite3_open(src, &restore); 160 161 if (ret != SQLITE_OK) { 162 ERROR_SQLITE(restore, "sqlite3_open"); 163 sqlite3_close(restore); 164 return (EPKG_FATAL); 165 } 166 167 pkg_emit_restore(); 168 ret = copy_database(restore, db->sqlite); 169 170 sqlite3_close(restore); 171 172 return (ret); 173 }