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