Branch data Line data Source code
1 : : /*
2 : : * libdpkg - Debian packaging suite library routines
3 : : * file.c - file handling functions
4 : : *
5 : : * Copyright © 1994, 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
7 : : *
8 : : * This is free software; you can redistribute it and/or modify
9 : : * it under the terms of the GNU General Public License as published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : *
13 : : * This is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include <config.h>
23 : : #include <compat.h>
24 : :
25 : : #include <sys/types.h>
26 : : #include <sys/stat.h>
27 : :
28 : : #include <errno.h>
29 : : #include <fcntl.h>
30 : : #include <unistd.h>
31 : :
32 : : #include <dpkg/dpkg.h>
33 : : #include <dpkg/i18n.h>
34 : : #include <dpkg/pager.h>
35 : : #include <dpkg/fdio.h>
36 : : #include <dpkg/buffer.h>
37 : : #include <dpkg/file.h>
38 : :
39 : : /**
40 : : * Check whether a filename is executable.
41 : : *
42 : : * @param filename The filename to check.
43 : : */
44 : : bool
45 : 4 : file_is_exec(const char *filename)
46 : : {
47 : : struct stat st;
48 : :
49 [ + + ]: 4 : if (stat(filename, &st) < 0)
50 : 1 : return false;
51 : :
52 [ - + ]: 3 : if (!S_ISREG(st.st_mode))
53 : 0 : return false;
54 : :
55 : 3 : return st.st_mode & 0111;
56 : : }
57 : :
58 : : /**
59 : : * Copy file ownership and permissions from one file to another.
60 : : *
61 : : * @param src The source filename.
62 : : * @param dst The destination filename.
63 : : */
64 : : void
65 : 0 : file_copy_perms(const char *src, const char *dst)
66 : : {
67 : : struct stat stab;
68 : :
69 [ # # ]: 0 : if (stat(src, &stab) == -1) {
70 [ # # ]: 0 : if (errno == ENOENT)
71 : 0 : return;
72 : 0 : ohshite(_("unable to stat source file '%.250s'"), src);
73 : : }
74 : :
75 [ # # ]: 0 : if (chown(dst, stab.st_uid, stab.st_gid) == -1)
76 : 0 : ohshite(_("unable to change ownership of target file '%.250s'"),
77 : : dst);
78 : :
79 [ # # ]: 0 : if (chmod(dst, (stab.st_mode & ~S_IFMT)) == -1)
80 : 0 : ohshite(_("unable to set mode of target file '%.250s'"), dst);
81 : : }
82 : :
83 : : static int
84 : 4 : file_slurp_fd(int fd, const char *filename, struct varbuf *vb,
85 : : struct dpkg_error *err)
86 : : {
87 : : struct stat st;
88 : :
89 [ - + ]: 4 : if (fstat(fd, &st) < 0)
90 : 0 : return dpkg_put_errno(err, _("cannot stat %s"), filename);
91 : :
92 [ + + ]: 4 : if (!S_ISREG(st.st_mode))
93 : 1 : return dpkg_put_error(err, _("%s is not a regular file"),
94 : : filename);
95 : :
96 [ + + ]: 3 : if (st.st_size == 0)
97 : 1 : return 0;
98 : :
99 : 2 : varbuf_init(vb, st.st_size);
100 [ - + ]: 2 : if (fd_read(fd, vb->buf, st.st_size) < 0)
101 : 0 : return dpkg_put_errno(err, _("cannot read %s"), filename);
102 : 2 : vb->used = st.st_size;
103 : :
104 : 2 : return 0;
105 : : }
106 : :
107 : : int
108 : 5 : file_slurp(const char *filename, struct varbuf *vb, struct dpkg_error *err)
109 : : {
110 : : int fd;
111 : : int rc;
112 : :
113 : 5 : varbuf_init(vb, 0);
114 : :
115 : 5 : fd = open(filename, O_RDONLY);
116 [ + + ]: 5 : if (fd < 0)
117 : 1 : return dpkg_put_errno(err, _("cannot open %s"), filename);
118 : :
119 : 4 : rc = file_slurp_fd(fd, filename, vb, err);
120 : :
121 : 4 : (void)close(fd);
122 : :
123 : 4 : return rc;
124 : : }
125 : :
126 : : static void
127 : 14 : file_lock_setup(struct flock *fl, short type)
128 : : {
129 : 14 : fl->l_type = type;
130 : 14 : fl->l_whence = SEEK_SET;
131 : 14 : fl->l_start = 0;
132 : 14 : fl->l_len = 0;
133 : 14 : fl->l_pid = 0;
134 : 14 : }
135 : :
136 : : /**
137 : : * Unlock a previously locked file.
138 : : */
139 : : void
140 : 7 : file_unlock(int lockfd, const char *lockfile, const char *lockdesc)
141 : : {
142 : : struct flock fl;
143 : :
144 [ - + ]: 7 : if (lockfd < 0)
145 : 0 : internerr("%s (%s) fd is %d < 0", lockdesc, lockfile, lockfd);
146 : :
147 : 7 : file_lock_setup(&fl, F_UNLCK);
148 : :
149 [ - + ]: 7 : if (fcntl(lockfd, F_SETLK, &fl) == -1)
150 : 0 : ohshite(_("unable to unlock %s"), lockdesc);
151 : 7 : }
152 : :
153 : : static void
154 : 7 : file_unlock_cleanup(int argc, void **argv)
155 : : {
156 : 7 : int lockfd = *(int *)argv[0];
157 : 7 : const char *lockfile = argv[1];
158 : 7 : const char *lockdesc = argv[2];
159 : :
160 : 7 : file_unlock(lockfd, lockfile, lockdesc);
161 : 7 : }
162 : :
163 : : /**
164 : : * Check if a file has a lock acquired.
165 : : *
166 : : * @param lockfd The file descriptor for the lock.
167 : : * @param filename The file name associated to the file descriptor.
168 : : */
169 : : bool
170 : 0 : file_is_locked(int lockfd, const char *filename)
171 : : {
172 : : struct flock fl;
173 : :
174 : 0 : file_lock_setup(&fl, F_WRLCK);
175 : :
176 [ # # ]: 0 : if (fcntl(lockfd, F_GETLK, &fl) == -1)
177 : 0 : ohshit(_("unable to check file '%s' lock status"), filename);
178 : :
179 [ # # # # ]: 0 : if (fl.l_type == F_WRLCK && fl.l_pid != getpid())
180 : 0 : return true;
181 : : else
182 : 0 : return false;
183 : : }
184 : :
185 : : /**
186 : : * Lock a file.
187 : : *
188 : : * @param lockfd The pointer to the lock file descriptor. It must be allocated
189 : : * statically as its addresses is passed to a cleanup handler.
190 : : * @param flags The lock flags specifying what type of locking to perform.
191 : : * @param filename The name of the file to lock.
192 : : * @param desc The description of the file to lock.
193 : : */
194 : : void
195 : 7 : file_lock(int *lockfd, enum file_lock_flags flags, const char *filename,
196 : : const char *desc)
197 : : {
198 : : struct flock fl;
199 : : int lock_cmd;
200 : :
201 : 7 : setcloexec(*lockfd, filename);
202 : :
203 : 7 : file_lock_setup(&fl, F_WRLCK);
204 : :
205 [ + - ]: 7 : if (flags == FILE_LOCK_WAIT)
206 : 7 : lock_cmd = F_SETLKW;
207 : : else
208 : 0 : lock_cmd = F_SETLK;
209 : :
210 [ - + ]: 7 : if (fcntl(*lockfd, lock_cmd, &fl) == -1) {
211 : : const char *warnmsg;
212 : :
213 [ # # # # ]: 0 : if (errno != EACCES && errno != EAGAIN)
214 : 0 : ohshite(_("unable to lock %s"), desc);
215 : :
216 : 0 : warnmsg = _("Note: removing the lock file is always wrong, "
217 : : "can damage the locked area\n"
218 : : "and the entire system. "
219 : : "See <https://wiki.debian.org/Teams/Dpkg/FAQ#db-lock>.");
220 : :
221 : 0 : file_lock_setup(&fl, F_WRLCK);
222 [ # # ]: 0 : if (fcntl(*lockfd, F_GETLK, &fl) == -1)
223 : 0 : ohshit(_("%s was locked by another process\n%s"),
224 : : desc, warnmsg);
225 : :
226 : 0 : ohshit(_("%s was locked by another process with pid %d\n%s"),
227 : : desc, fl.l_pid, warnmsg);
228 : : }
229 : :
230 : 7 : push_cleanup(file_unlock_cleanup, ~0, 3, lockfd, filename, desc);
231 : 7 : }
232 : :
233 : : void
234 : 0 : file_show(const char *filename)
235 : : {
236 : : struct pager *pager;
237 : : struct dpkg_error err;
238 : : int fd, rc;
239 : :
240 [ # # ]: 0 : if (filename == NULL)
241 : 0 : internerr("filename is NULL");
242 : :
243 : 0 : fd = open(filename, O_RDONLY);
244 [ # # ]: 0 : if (fd < 0)
245 : 0 : ohshite(_("cannot open file %s"), filename);
246 : :
247 : 0 : pager = pager_spawn(_("pager to show file"));
248 : 0 : rc = fd_fd_copy(fd, STDOUT_FILENO, -1, &err);
249 : 0 : pager_reap(pager);
250 : :
251 : 0 : close(fd);
252 : :
253 [ # # # # ]: 0 : if (rc < 0 && err.syserrno != EPIPE) {
254 : 0 : errno = err.syserrno;
255 : 0 : ohshite(_("cannot write file %s into the pager"), filename);
256 : : }
257 : 0 : }
|