libreport 2.13.1
A tool to inform users about various problems on the running system
dump_dir.h
1/*
2 On-disk storage of problem data
3
4 Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
5 Copyright (C) 2009 RedHat inc.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*/
21#ifndef LIBREPORT_DUMP_DIR_H_
22#define LIBREPORT_DUMP_DIR_H_
23
24/* For const_string_vector_const_ptr_t */
25#include "libreport_types.h"
26#include "report_result.h"
27
28#include <stdint.h>
29#include <stdio.h>
30
31/* For DIR */
32#include <sys/types.h>
33#include <dirent.h>
34
35/* For 'struct stat' */
36#include <sys/stat.h>
37
38/* Fore GList */
39#include <glib.h>
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45/* Utility function */
46int create_symlink_lockfile(const char *filename, const char *pid_str);
47int create_symlink_lockfile_at(int dir_fd, const char *filename, const char *pid_str);
48
49/* Opens filename for reading relatively to a directory represented by dir_fd.
50 * The function fails if the file is symbolic link, directory or hard link.
51 */
52int secure_openat_read(int dir_fd, const char *filename);
53
54/******************************************************************************/
55/* Global variables */
56/******************************************************************************/
57
58/* UID of super-user (default 0)
59 *
60 * This variable is used by the dd* functions when they access security
61 * sensitive elements. The functions will ONLY TRUST the contents of those
62 * elements that ARE OWNED by super-user.
63 */
64extern uid_t dd_g_super_user_uid;
65
66/* GID of a dump diretory created via dd_create() with uid != -1
67 *
68 * The default value is -1 which means that the dd* functions must ignore this
69 * variable.
70 *
71 * Initialize this variable only if you don't want to use the default group
72 * ('abrt').
73 */
74extern gid_t dd_g_fs_group_gid;
75
76/******************************************************************************/
77/* Dump Directory */
78/******************************************************************************/
79
80enum dump_dir_flags {
81 DD_FAIL_QUIETLY_ENOENT = (1 << 0),
82 DD_FAIL_QUIETLY_EACCES = (1 << 1),
83 /* Open symlinks. dd_* funcs don't open symlinks by default */
84 DD_OPEN_FOLLOW = (1 << 2),
85 DD_OPEN_READONLY = (1 << 3),
86 DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE = (1 << 4),
87 DD_DONT_WAIT_FOR_LOCK = (1 << 5),
88 /* Create the new dump directory with parent directories (mkdir -p)*/
89 DD_CREATE_PARENTS = (1 << 6),
90 /* Initializes internal data, opens file descriptors and returns the
91 * structure. This flag is useful for testing whether a directory
92 * exists and to perform stat operations.
93 */
94 DD_OPEN_FD_ONLY = (1 << 7),
95};
96
97struct dump_dir {
98 char *dd_dirname;
99 DIR *next_dir;
100 int locked;
101 uid_t dd_uid;
102 gid_t dd_gid;
103 /* mode of saved files */
104 mode_t mode;
105 time_t dd_time;
106 char *dd_type;
107
108 /* In case of recursive locking the first caller owns the lock and is
109 * responsible for unlocking. The consecutive dd_lock() callers acquire the
110 * lock but are not able to unlock the dump directory.
111 */
112 int owns_lock;
113 int dd_fd;
114 /* Never use this member directly, it is intialized on demand in
115 * dd_get_meta_data_dir_fd()
116 */
117 int dd_md_fd;
118};
119
120void dd_close(struct dump_dir *dd);
121
122/* Opens the given path
123 */
124struct dump_dir *dd_opendir(const char *dir, int flags);
125
126/* Re-opens a dump_dir opened with DD_OPEN_FD_ONLY.
127 *
128 * The passed dump_dir must not be used any more and the return value must be
129 * used instead.
130 *
131 * The passed flags must not contain DD_OPEN_FD_ONLY.
132 *
133 * The passed dump_dir must not be already locked.
134 */
135struct dump_dir *dd_fdopendir(struct dump_dir *dd, int flags);
136
137/* Creates a new directory with internal files
138 *
139 * The functions creates a new directory which remains owned by the user of the
140 * process until dd_reset_ownership() is called.
141 *
142 * The function logs error messages in case of errors.
143 *
144 * @param dir Full file system path of the new directory
145 * @param uid Desired file system owner of the new directory or -1 if the owner
146 * should stay untouched even after calling dd_reset_ownership().
147 * @param mode File system mode of the new directory.
148 * @param flags See 'enum dump_dir_flags'
149 * @return Initialized struct dump_dir of NULL
150 */
151struct dump_dir *dd_create_skeleton(const char *dir, uid_t uid, mode_t mode, int flags);
152
153int dd_reset_ownership(struct dump_dir *dd);
154
155/* Pass uid = (uid_t)-1L to disable chown'ing of newly created files
156 * (IOW: if you aren't running under root):
157 */
158struct dump_dir *dd_create(const char *dir, uid_t uid, mode_t mode);
159
160/* Creates the basic files except 'type' and sets the dump dir owner to passed
161 * 'uid'.
162 *
163 * The file 'type' is required and must be added with dd_save_text().
164 *
165 * If you want to have owner different than the problem 'uid', than pass -1 and
166 * add the file 'uid' with dd_save_text()
167 *
168 * List of created files:
169 * - time
170 * - last_occurrence
171 * - uid
172 * - kernel
173 * - architecture
174 * - hostname
175 * - os_info
176 * - os_release
177 *
178 * If any of these files has a counterpart in a chroot directory (os_info,
179 * os_relase), creates an element with the prefix "root_"
180 */
181void dd_create_basic_files(struct dump_dir *dd, uid_t uid, const char *chroot_dir);
182int dd_exist(const struct dump_dir *dd, const char *path);
183void dd_sanitize_mode_and_owner(struct dump_dir *dd);
184
185/* Initializes an iterator going through all dump directory items.
186 *
187 * @returns NULL if the iterator cannot be initialized; otherwise returns
188 * the result of opendir(). Do not use the return value after the iteration is
189 * finished or after calling dd_clear_next_file().
190 */
191DIR *dd_init_next_file(struct dump_dir *dd);
192
193/* Iterates over all dump directory item names
194 *
195 * Initialize the iterator by calling dd_init_next_file(). When iteration is
196 * finished, calls dd_clear_next_file().
197 *
198 * @returns 1 if the next item was read; otherwise return 0.
199 */
200int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name);
201
202/* Destroys the next file iterator and cleans dump directory internal structures
203 *
204 * Calling dd_get_next_file() after this function returns will return 0. This
205 * function also invalidates the return value of dd_init_next_file().
206 */
207void dd_clear_next_file(struct dump_dir *dd);
208
209char *load_text_file(const char *path, unsigned flags);
210
211char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned flags);
212char* dd_load_text(const struct dump_dir *dd, const char *name);
213int dd_load_int32(const struct dump_dir *dd, const char *name, int32_t *value);
214int dd_load_uint32(const struct dump_dir *dd, const char *name, uint32_t *value);
215int dd_load_int64(const struct dump_dir *dd, const char *name, int64_t *value);
216int dd_load_uint64(const struct dump_dir *dd, const char *name, uint64_t *value);
217
218/* Returns value of environment variable with given name.
219 *
220 * @param dd Dump directory
221 * @param name Variables's name
222 * @param value Return value.
223 * @return 0 no success, or negative value if an error occurred (-ENOENT if the
224 * given dd does not support environment variables).
225 */
226int dd_get_env_variable(struct dump_dir *dd, const char *name, char **value);
227
228void dd_save_text(struct dump_dir *dd, const char *name, const char *data);
229void dd_save_binary(struct dump_dir *dd, const char *name, const char *data, unsigned size);
230int dd_copy_file(struct dump_dir *dd, const char *name, const char *source_path);
231int dd_copy_file_unpack(struct dump_dir *dd, const char *name, const char *source_path);
232
233/* Create an item of the given name with contents of the given file (see man openat)
234 *
235 * @param dd Dump directory
236 * @param name Item's name
237 * @param src_dir_fd Source directory's file descriptor
238 * @param src_name Source file name
239 * @return 0 no success, or negative value if an error occurred
240 */
241int dd_copy_file_at(struct dump_dir *dd, const char *name, int src_dir_fd, const char *src_name);
242
243/* Creates/overwrites an element with data read from a file descriptor
244 *
245 * @param dd Dump directory
246 * @param name The name of the element
247 * @param fd The file descriptor
248 * @param flags libreport_copyfd_flags
249 * @param maxsize Limit for number of written Bytes. (0 for unlimited).
250 * @return Number of read Bytes. If the return value is greater than the maxsize
251 * the file descriptor content was truncated to the maxsize. The return value
252 * is not size of the file descriptor.
253 */
254off_t dd_copy_fd(struct dump_dir *dd, const char *name, int fd, int copy_flags, off_t maxsize);
255
256/* Stats dump dir elements
257 *
258 * @param dd Dump Directory
259 * @param name The name of the element
260 * @param statbuf See 'man 2 stat'
261 * @return -EINVAL if name is invalid element name, -EMEDIUMTYPE if name is not
262 * regular file, -errno on errors and 0 on success.
263 */
264int dd_item_stat(struct dump_dir *dd, const char *name, struct stat *statbuf);
265
266/* Returns value less than 0 if any error occured; otherwise returns size of an
267 * item in Bytes. If an item does not exist returns 0 instead of an error
268 * value.
269 */
270long dd_get_item_size(struct dump_dir *dd, const char *name);
271
272/* Returns the number of items in the dump directory (does not count meta-data).
273 *
274 * @return Negative number on errors (-errno). Otherwise number of dump
275 * directory items.
276 */
277int dd_get_items_count(struct dump_dir *dd);
278
279/* Deletes an item from dump directory
280 * On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
281 * For more about errno see unlink documentation
282 */
283int dd_delete_item(struct dump_dir *dd, const char *name);
284
285/* Returns a file descriptor for the given name. The function is limited to open
286 * an element read only, write only or create new.
287 *
288 * O_RDONLY - opens an existing item for reading
289 * O_RDWR - removes an item, creates its file and opens the file for reading and writing
290 *
291 * @param dd Dump directory
292 * @param name The name of the item
293 * @param flags One of these : O_RDONLY, O_RDWR
294 * @return Negative number on error
295 */
296int dd_open_item(struct dump_dir *dd, const char *name, int flags);
297
298/* Returns a FILE for the given name. The function is limited to open
299 * an element read only, write only or create new.
300 *
301 * O_RDONLY - opens an existing file for reading
302 * O_RDWR - removes an item, creates its file and opens the file for reading and writing
303 *
304 * @param dd Dump directory
305 * @param name The name of the item
306 * @param flags One of these : O_RDONLY, O_RDWR
307 * @return NULL on error
308 */
309FILE *dd_open_item_file(struct dump_dir *dd, const char *name, int flags);
310
311/* Returns 0 if directory is deleted or not found */
312int dd_delete(struct dump_dir *dd);
313int dd_rename(struct dump_dir *dd, const char *new_path);
314/* Changes owner of dump dir
315 * Uses two different strategies selected at build time by
316 * DUMP_DIR_OWNED_BY_USER configuration:
317 * <= 0 : owner = abrt user's uid, group = new_uid's gid
318 * > 0 : owner = new_uid, group = abrt group's gid
319 *
320 * On success, zero is returned. On error, -1 is returned.
321 */
322int dd_chown(struct dump_dir *dd, uid_t new_uid);
323
324/* Returns the number of Bytes consumed by the dump directory.
325 *
326 * @param flags For the future needs (count also meta-data, ...).
327 * @return Negative number on errors (-errno). Otherwise size in Bytes.
328 */
329off_t dd_compute_size(struct dump_dir *dd, int flags);
330
331/* Sets a new owner (does NOT chown the directory)
332 *
333 * Does not validate the passed uid.
334 * The given dump_dir must be opened for writing.
335 */
336int dd_set_owner(struct dump_dir *dd, uid_t owner);
337
338/* Makes the dump directory owned by nobody.
339 *
340 * The directory will be accessible for all users.
341 * The given dump_dir must be opened for writing.
342 */
343int dd_set_no_owner(struct dump_dir *dd);
344
345/* Gets the owner
346 *
347 * If meta-data misses owner, returns fs owner.
348 * Can be used with DD_OPEN_FD_ONLY.
349 */
350uid_t dd_get_owner(struct dump_dir *dd);
351
352/* Returns UNIX time stamp of the first occurrence of the problem.
353 *
354 * @param dd Examined dump directory
355 * @returns On success, the value of time of the first occurrence in seconds
356 * since the Epoch is returned. On error, ((time_t) -1) is returned, and errno
357 * is set appropriately (ENODATA).
358 */
359time_t dd_get_first_occurrence(struct dump_dir *dd);
360
361/* Returns UNIX time stamp of the last occurrence of the problem.
362 *
363 * @param dd Examined dump directory
364 * @returns The returned value is never lower than the value returned by
365 * dd_get_first_occurrence(). On success, the value of time of the first
366 * occurrence in seconds since the Epoch is returned.On error, ((time_t) -1) is
367 * returned, and errno is set appropriately (ENODATA).
368 */
369time_t dd_get_last_occurrence(struct dump_dir *dd);
370
371/* Appends a new unique line to the list of report results
372 *
373 * If the reported_to data already contains the given line, the line will not
374 * be added again.
375 *
376 * @param reported_to The data
377 * @param line The appended line
378 * @return 1 if the line was added at the end of the reported_to; otherwise 0.
379 */
380int libreport_add_reported_to_data(char **reported_to, const char *line);
381
382/* Appends a new unique entry to the list of report results
383 *
384 * result->label must be non-empty string which does not contain ':' character.
385 *
386 * The function converts the result to a valid reported_to line and calls
387 * libreport_add_reported_to_data().
388 *
389 * @param reported_to The data
390 * @param result The appended entry
391 * @return -EINVAL if result->label is invalid; otherwise return value of
392 * libreport_add_reported_to_data
393 */
394int libreport_add_reported_to_entry_data(char **reported_to, struct report_result *result);
395
396/* This is a wrapper of libreport_add_reported_to_data which accepts 'struct dump_dir *'
397 * in the first argument instead of 'char **'. The added line is stored in
398 * 'reported_to' dump directory file.
399 */
400void libreport_add_reported_to(struct dump_dir *dd, const char *line);
401
402/* This is a wrapper of libreport_add_reported_to_entry_data which accepts 'struct
403 * dump_dir *' in the first argument instead of 'char **'. The added entry is
404 * stored in 'reported_to' dump directory file.
405 */
406void libreport_add_reported_to_entry(struct dump_dir *dd, struct report_result *result);
407
408report_result_t *libreport_find_in_reported_to_data(const char *reported_to, const char *report_label);
409report_result_t *libreport_find_in_reported_to(struct dump_dir *dd, const char *report_label);
410GList *libreport_read_entire_reported_to_data(const char* reported_to);
411GList *libreport_read_entire_reported_to(struct dump_dir *dd);
412
413
414void delete_dump_dir(const char *dirname);
415/* Checks dump dir accessibility for particular uid.
416 *
417 * If the directory doesn't exist the directory is not accessible and errno is
418 * set to ENOTDIR.
419 *
420 * Returns non zero if dump dir is accessible otherwise return 0 value.
421 */
422int dump_dir_accessible_by_uid(const char *dirname, uid_t uid);
423/* Returns the same information as dump_dir_accessible_by_uid
424 *
425 * The passed dump_dir can be opened with DD_OPEN_FD_ONLY
426 */
427int dd_accessible_by_uid(struct dump_dir *dd, uid_t uid);
428
429enum {
430 DD_STAT_ACCESSIBLE_BY_UID = 1,
431 DD_STAT_OWNED_BY_UID = DD_STAT_ACCESSIBLE_BY_UID << 1,
432 DD_STAT_NO_OWNER = DD_STAT_OWNED_BY_UID << 1,
433};
434
435/* Gets information about a dump directory for particular uid.
436 *
437 * If the directory doesn't exist the directory is not accessible and errno is
438 * set to ENOTDIR.
439 *
440 * Returns negative number if error occurred otherwise returns 0 or positive number.
441 */
442int dump_dir_stat_for_uid(const char *dirname, uid_t uid);
443/* Returns the same information as dump_dir_stat_for_uid
444 *
445 * The passed dump_dir can be opened with DD_OPEN_FD_ONLY
446 */
447int dd_stat_for_uid(struct dump_dir *dd, uid_t uid);
448
449/* creates not_reportable file in the problem directory and saves the
450 reason to it, which prevents libreport from reporting the problem
451 On success, zero is returned.
452 On error, -1 is returned and an error message is logged.
453 - this could probably happen only if the dump dir is not locked
454*/
455int dd_mark_as_notreportable(struct dump_dir *dd, const char *reason);
456
457typedef int (*save_data_call_back)(struct dump_dir *, void *args);
458
459/* Saves data in a new dump directory
460 *
461 * Creates a new dump directory in "problem dump location", adds the basic
462 * information to the new directory, calls given callback to allow callees to
463 * customize the dump dir contents (save problem data) and commits the dump
464 * directory (makes the directory visible for a problem daemon).
465 */
466struct dump_dir *create_dump_dir(const char *base_dir_name, const char *type,
467 uid_t uid, save_data_call_back save_data, void *args);
468
469struct dump_dir *create_dump_dir_ext(const char *base_dir_name, const char *type,
470 pid_t pid, uid_t uid, save_data_call_back save_data, void *args);
471
472/* Creates a new archive from the dump directory contents
473 *
474 * The dd argument must be opened for reading.
475 *
476 * The archive_name must not exist. The file will be created with 0600 mode.
477 *
478 * The archive type is deduced from archive_name suffix. The supported archive
479 * suffixes are the following:
480 * - '.tag.gz' (note: the implementation uses child gzip process)
481 *
482 * The archive will include only the files that are not in the exclude_elements
483 * list. See libreport_get_global_always_excluded_elements().
484 *
485 * The argument "flags" is currently unused.
486 *
487 * @return 0 on success; otherwise non-0 value. -ENOSYS if archive type is not
488 * supported. -EEXIST if the archive file already exists. -ECHILD if child
489 * process fails. Other negative values can be converted to errno values by
490 * turning them positive.
491 */
492int dd_create_archive(struct dump_dir *dd, const char *archive_name,
493 const_string_vector_const_ptr_t exclude_elements, int flags);
494
495#ifdef __cplusplus
496}
497#endif
498
499#endif