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