Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2020 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions
6 : : * are met:
7 : : * 1. Redistributions of source code must retain the above copyright
8 : : * notice, this list of conditions and the following disclaimer
9 : : * in this position and unchanged.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : *
14 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 : : */
25 : :
26 : : #include <errno.h>
27 : : #include <fcntl.h>
28 : : #include <time.h>
29 : :
30 : : #include "pkg.h"
31 : : #include "private/event.h"
32 : : #include "private/pkg.h"
33 : :
34 : : static int
35 : 2 : register_backup(struct pkgdb *db, int fd, const char *path)
36 : : {
37 : : struct pkgdb_it *it;
38 : 2 : struct pkg *pkg = NULL;
39 : : time_t t;
40 : : char buf[BUFSIZ];
41 : : char *sum;
42 : : struct pkg_file *f;
43 : : char *lpath;
44 : : struct stat st;
45 : : pkghash_entry *e;
46 : : int retcode;
47 : :
48 : 2 : sum = pkg_checksum_generate_fileat(fd, RELATIVE_PATH(path), PKG_HASH_TYPE_SHA256_HEX);
49 : :
50 : 2 : it = pkgdb_query(db, "compat-libraries", MATCH_EXACT);
51 [ - + ]: 2 : if (it != NULL) {
52 : 2 : pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_FILES);
53 : 2 : pkgdb_it_free(it);
54 : 2 : }
55 [ + + ]: 2 : if (pkg == NULL) {
56 [ - + ]: 1 : if (pkg_new(&pkg, PKG_FILE) != EPKG_OK) {
57 : 0 : return (EPKG_FATAL);
58 : : }
59 : 1 : pkg->name = xstrdup("compat-libraries");
60 : 1 : pkg->origin = xstrdup("compat/libraries");
61 : 1 : pkg->comment = xstrdup("Compatibility libraries saved during local packages upgrade\n");
62 : 1 : pkg->desc = xstrdup("Compatibility libraries saved during local packages upgrade\n");
63 : 1 : pkg->maintainer = xstrdup("root@localhost");
64 : 1 : pkg->www = xstrdup("N/A");
65 : 1 : pkg->prefix = xstrdup("/");
66 : 1 : pkg->abi = "*";
67 : 1 : }
68 : 2 : free(pkg->version);
69 : 2 : t = time(NULL);
70 : 2 : strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&t));
71 [ + - ]: 2 : if ((e = pkghash_get(pkg->filehash, path)) != NULL) {
72 [ # # # # : 0 : DL_DELETE(pkg->files, (struct pkg_file *)e->value);
# # # # ]
73 : 0 : pkg_file_free(e->value);
74 : 0 : pkghash_del(pkg->filehash, path);
75 : 0 : }
76 : 2 : xasprintf(&lpath, "%s/%s", ctx.backup_library_path, path);
77 : 2 : pkg_addfile(pkg, lpath, sum, false);
78 : 2 : free(lpath);
79 : 2 : pkg->version = xstrdup(buf);
80 : 2 : pkg_analyse_files(NULL, pkg, ctx.pkg_rootdir);
81 : 2 : pkg_open_root_fd(pkg);
82 : 2 : f = NULL;
83 [ + + ]: 5 : while (pkg_files(pkg, &f) == EPKG_OK) {
84 [ - + ]: 3 : if (fstatat(pkg->rootfd, RELATIVE_PATH(f->path), &st, AT_SYMLINK_NOFOLLOW) != -1)
85 : 3 : pkg->flatsize += st.st_size;
86 : : }
87 : 2 : retcode = pkgdb_register_pkg(db, pkg, 0, "backuplib");
88 [ - + ]: 2 : if (retcode == EPKG_OK)
89 : 2 : pkgdb_register_finale(db, EPKG_OK, "backuplib");
90 : 2 : return (retcode);
91 : 2 : }
92 : :
93 : : void
94 : 2 : backup_library(struct pkgdb *db, struct pkg *p, const char *path)
95 : : {
96 : 2 : const char *libname = strrchr(path, '/');
97 : : char buf[BUFSIZ];
98 : : char *outbuf;
99 : : int from, to, backupdir;
100 : : ssize_t nread, nwritten;
101 : :
102 : 2 : pkg_open_root_fd(p);
103 : 2 : to = -1;
104 : :
105 [ + - ]: 2 : if (libname == NULL)
106 : 0 : return;
107 : : /* skip the initial / */
108 : 2 : libname++;
109 : :
110 : 2 : from = openat(p->rootfd, RELATIVE_PATH(path), O_RDONLY);
111 [ - + ]: 2 : if (from == -1) {
112 : 0 : pkg_debug(2, "unable to backup %s:%s", path, strerror(errno));
113 : 0 : return;
114 : : }
115 : :
116 [ + + ]: 2 : if (mkdirat(p->rootfd, RELATIVE_PATH(ctx.backup_library_path), 0755) == -1) {
117 [ + - ]: 1 : if (!mkdirat_p(p->rootfd, RELATIVE_PATH(ctx.backup_library_path))) {
118 : 0 : pkg_emit_errno("Impossible to create the library backup "
119 : 0 : "directory", ctx.backup_library_path);
120 : 0 : close(from);
121 : 0 : return;
122 : : }
123 : 1 : }
124 : 2 : backupdir = openat(p->rootfd, RELATIVE_PATH(ctx.backup_library_path),
125 : : O_DIRECTORY);
126 [ + - ]: 2 : if (backupdir == -1) {
127 : 0 : pkg_emit_error("Impossible to open the library backup "
128 : 0 : "directory %s", ctx.backup_library_path);
129 : 0 : goto out;
130 : : }
131 : :
132 : : /*
133 : : * always overwrite the existing backup library, it might be older than
134 : : * this one
135 : : */
136 : : /* first always unlink to ensure we are not truncating a used library */
137 : 2 : unlinkat(backupdir, libname, 0);
138 : 2 : to = openat(backupdir, libname, O_EXCL|O_CREAT|O_WRONLY, 0644);
139 [ + - ]: 2 : if (to == -1) {
140 : 0 : pkg_emit_errno("Impossible to create the backup library", libname);
141 : 0 : goto out;
142 : : }
143 : :
144 [ + + ]: 20 : while ((nread = read(from, buf, sizeof(buf))) > 0) {
145 : 18 : outbuf = buf;
146 : 18 : do {
147 : 18 : nwritten = write(to, outbuf, nread);
148 [ + - ]: 18 : if (nwritten >= 0) {
149 : 18 : nread -= nwritten;
150 : 18 : outbuf += nwritten;
151 [ # # ]: 18 : } else if (errno != EINTR) {
152 : 0 : goto out;
153 : : }
154 [ + - ]: 18 : } while (nread > 0);
155 : : }
156 : :
157 [ - + ]: 2 : if (nread == 0) {
158 [ + - ]: 2 : if (close(to) < 0) {
159 : 0 : to = -1;
160 : 0 : goto out;
161 : : }
162 : 2 : close(from);
163 : 2 : register_backup(db, backupdir, libname);
164 : 2 : close(backupdir);
165 : 2 : return;
166 : : }
167 : :
168 : :
169 : : out:
170 : 0 : pkg_emit_errno("Fail to backup the library", libname);
171 [ # # ]: 0 : if (backupdir >= 0)
172 : 0 : close(backupdir);
173 [ # # ]: 0 : if (from >= 0)
174 : 0 : close(from);
175 [ # # ]: 0 : if (to >= 0)
176 : 0 : close(to);
177 : 2 : }
|