[go: up one dir, main page]

File: debug_file.c

package info (click to toggle)
cctools 9.9-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 44,624 kB
  • sloc: ansic: 192,539; python: 20,827; cpp: 20,199; sh: 11,719; perl: 4,106; xml: 3,688; makefile: 1,224
file content (120 lines) | stat: -rw-r--r-- 2,811 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright (C) 2014- The University of Notre Dame
This software is distributed under the GNU General Public License.
See the file COPYING for details.
*/

#include "catch.h"
#include "debug.h"
#include "full_io.h"
#include "stringtools.h"
#include "path.h"

#include <unistd.h>
#include <fcntl.h>

#include <sys/stat.h>

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

static int file_fd = -1;
static struct stat file_stat;
static char file_path[PATH_MAX];
/* Default size of 0 will not roll over debug info. */
static off_t file_size_max = 0;

/* define custom debug for catch */
#undef debug
#define debug(l,fmt,...) fprintf(stderr, "%s: " fmt "\n", #l, __VA_ARGS__);

int debug_file_reopen (void)
{
	int rc;
	if (strlen(file_path)) {
		int flags;
		close(file_fd);
		CATCHUNIX(file_fd = open(file_path, O_CREAT|O_APPEND|O_WRONLY|O_NOCTTY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
		CATCHUNIX(flags = fcntl(file_fd, F_GETFD));
		flags |= FD_CLOEXEC;
		CATCHUNIX(fcntl(file_fd, F_SETFD, flags));
		CATCHUNIX(fstat(file_fd, &file_stat)); /* save inode */
		/* canonicalize the debug_file path for future operations */
		{
			char tmp[PATH_MAX] = "";
			CATCHUNIX(realpath(file_path, tmp) == NULL ? -1 : 0);
			memcpy(file_path, tmp, sizeof(file_path));
		}
	}
	rc = 0;
	goto out;
out:
	return RCUNIX(rc);
}

void debug_file_write (INT64_T flags, const char *str)
{
	int rc;

	/* Beware this code is racey and debug messages may be lost during
	 * rotations. Two processes rotating logs at the same time may create two
	 * new logs. The stat on the filename and inode comparison catches this
	 * after one lost debug message.
	 */

	if (file_size_max > 0) {
		struct stat info;
		rc = stat(file_path, &info);
		if (rc == 0) {
			if (info.st_size >= file_size_max) {
				char old[PATH_MAX];
				string_nformat(old, sizeof(old), "%s.old", file_path);
				rename(file_path, old);
				debug_file_reopen();
			} else if (info.st_ino != file_stat.st_ino) {
				/* another process rotated the log */
				debug_file_reopen();
			}
		} else {
			fprintf(stderr, "couldn't stat debug file: %s\n", strerror(errno));
			abort();
		}
	}

	rc = full_write(file_fd, str, strlen(str));
	if (rc == -1) {
		fprintf(stderr, "couldn't write to debug file: %s\n", strerror(errno));
		abort();
	}
}

int debug_file_path (const char *path)
{
	strncpy(file_path, path, sizeof(file_path)-1);
	return debug_file_reopen();
}

void debug_file_size (off_t size)
{
	file_size_max = size;
}

void debug_file_rename (const char *suffix)
{
	if (strlen(file_path)) {
		char old[PATH_MAX] = "";

		string_nformat(old, sizeof(old), "%s.%s", file_path, suffix);
		rename(file_path, old);
		debug_file_reopen();
	}
}

/* vim: set noexpandtab tabstop=4: */