aboutsummaryrefslogtreecommitdiffstats
path: root/src/ftee/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftee/main.c')
-rw-r--r--src/ftee/main.c245
1 files changed, 0 insertions, 245 deletions
diff --git a/src/ftee/main.c b/src/ftee/main.c
deleted file mode 100644
index 0e37f0b72..000000000
--- a/src/ftee/main.c
+++ /dev/null
@@ -1,245 +0,0 @@
1/*
2 * Copyright (C) 2014-2018 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "ftee.h"
21#include <errno.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#define MAXBUF 512
26
27static unsigned char buf[MAXBUF];
28
29static FILE *out_fp = NULL;
30static int out_cnt = 0;
31static int out_max = 500 * 1024;
32
33static void log_close(void) {
34 if (out_fp) {
35 fclose(out_fp);
36 out_fp = NULL;
37 }
38}
39
40static void log_rotate(const char *fname) {
41 struct stat s;
42 int index = strlen(fname);
43 char *name1 = malloc(index + 2 + 1);
44 char *name2 = malloc(index + 2 + 1);
45 if (!name1 || !name2)
46 errExit("malloc");
47 strcpy(name1, fname);
48 strcpy(name2, fname);
49 fflush(0);
50
51 // delete filename.5
52 sprintf(name1 + index, ".5");
53 if (stat(name1, &s) == 0) {
54 int rv = unlink(name1);
55 if (rv == -1)
56 perror("unlink");
57 }
58
59 // move files 1 to 4 down one position
60 sprintf(name2 + index, ".4");
61 if (stat(name2, &s) == 0) {
62 int rv = rename(name2, name1);
63 if (rv == -1)
64 perror("rename");
65 }
66
67 sprintf(name1 + index, ".3");
68 if (stat(name1, &s) == 0) {
69 int rv = rename(name1, name2);
70 if (rv == -1)
71 perror("rename");
72 }
73
74 sprintf(name2 + index, ".2");
75 if (stat(name2, &s) == 0) {
76 /* coverity[toctou] */
77 int rv = rename(name2, name1);
78 if (rv == -1)
79 perror("rename");
80 }
81
82 sprintf(name1 + index, ".1");
83 if (stat(name1, &s) == 0) {
84 int rv = rename(name1, name2);
85 if (rv == -1)
86 perror("rename");
87 }
88
89 // move the first file
90 if (out_fp)
91 fclose(out_fp);
92
93 out_fp = NULL;
94 if (stat(fname, &s) == 0) {
95 int rv = rename(fname, name1);
96 if (rv == -1)
97 perror("rename");
98 }
99
100 free(name1);
101 free(name2);
102}
103
104static void log_write(const unsigned char *str, int len, const char *fname) {
105 assert(fname);
106
107 if (out_fp == NULL) {
108 out_fp = fopen(fname, "w");
109 if (!out_fp) {
110 fprintf(stderr, "Error: cannot open log file %s\n", fname);
111 exit(1);
112 }
113 out_cnt = 0;
114 }
115
116 // rotate files
117 out_cnt += len;
118 if (out_cnt >= out_max) {
119 log_rotate(fname);
120
121 // reopen the first file
122 if (out_fp)
123 fclose(out_fp);
124 out_fp = fopen(fname, "w");
125 if (!out_fp) {
126 fprintf(stderr, "Error: cannot open log file %s\n", fname);
127 exit(1);
128 }
129 out_cnt = len;
130 }
131
132 int rv = fwrite(str, len, 1, out_fp);
133 (void) rv;
134 fflush(0);
135}
136
137
138// return 1 if the file is a directory
139static int is_dir(const char *fname) {
140 assert(fname);
141 if (*fname == '\0')
142 return 0;
143
144 // if fname doesn't end in '/', add one
145 int rv;
146 struct stat s;
147 if (fname[strlen(fname) - 1] == '/')
148 rv = stat(fname, &s);
149 else {
150 char *tmp;
151 if (asprintf(&tmp, "%s/", fname) == -1) {
152 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
153 exit(1);
154 }
155 rv = stat(tmp, &s);
156 free(tmp);
157 }
158
159 if (rv == -1)
160 return 0;
161
162 if (S_ISDIR(s.st_mode))
163 return 1;
164
165 return 0;
166}
167
168// return 1 if the file is a link
169static int is_link(const char *fname) {
170 assert(fname);
171 if (*fname == '\0')
172 return 0;
173
174 struct stat s;
175 if (lstat(fname, &s) == 0) {
176 if (S_ISLNK(s.st_mode))
177 return 1;
178 }
179
180 return 0;
181}
182
183static void usage(void) {
184 printf("Usage: ftee filename\n");
185}
186
187int main(int argc, char **argv) {
188 if (argc < 2) {
189 fprintf(stderr, "Error: please provide a filename to store the program output\n");
190 usage();
191 exit(1);
192 }
193 if (strcmp(argv[1], "--help") == 0) {
194 usage();
195 return 0;
196 }
197 char *fname = argv[1];
198
199
200 // do not accept directories, links, and files with ".."
201 if (strstr(fname, "..") || is_link(fname) || is_dir(fname))
202 goto errexit;
203
204 struct stat s;
205 if (stat(fname, &s) == 0) {
206 // check permissions
207 if (s.st_uid != getuid() || s.st_gid != getgid())
208 goto errexit;
209
210 // check hard links
211 if (s.st_nlink != 1)
212 goto errexit;
213 }
214
215 // check if we can append to this file
216 /* coverity[toctou] */
217 FILE *fp = fopen(fname, "a");
218 if (!fp)
219 goto errexit;
220 fclose(fp);
221
222
223 // preserve the last log file
224 log_rotate(fname);
225
226 setvbuf (stdout, NULL, _IONBF, 0);
227 while(1) {
228 int n = read(0, buf, sizeof(buf));
229 if (n < 0 && errno == EINTR)
230 continue;
231 if (n <= 0)
232 break;
233
234 int rv = fwrite(buf, n, 1, stdout);
235 (void) rv;
236 log_write(buf, n, fname);
237 }
238
239 log_close();
240 return 0;
241
242errexit:
243 fprintf(stderr, "Error ftee: invalid output file.\n");
244 return 1;
245}