tor  0.4.2.1-alpha-dev
files.c
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
12 #ifdef _WIN32
13 #include <windows.h>
14 #endif
15 
16 #include "lib/fs/files.h"
17 #include "lib/fs/path.h"
19 #include "lib/log/log.h"
20 #include "lib/log/util_bug.h"
21 #include "lib/log/escape.h"
22 #include "lib/err/torerr.h"
23 #include "lib/malloc/malloc.h"
24 #include "lib/sandbox/sandbox.h"
25 #include "lib/string/printf.h"
26 #include "lib/string/util_string.h"
27 #include "lib/fdio/fdio.h"
28 
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #ifdef HAVE_SYS_STAT_H
33 #include <sys/stat.h>
34 #endif
35 #ifdef HAVE_UTIME_H
36 #include <utime.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 #include <sys/time.h>
40 #endif
41 #ifdef HAVE_FCNTL_H
42 #include <fcntl.h>
43 #endif
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #include <errno.h>
48 #include <stdio.h>
49 #include <string.h>
50 
53 int
54 tor_open_cloexec(const char *path, int flags, unsigned mode)
55 {
56  int fd;
57  const char *p = sandbox_intern_string(path);
58 #ifdef O_CLOEXEC
59  fd = open(p, flags|O_CLOEXEC, mode);
60  if (fd >= 0)
61  return fd;
62  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
63  * even though we were built on a system with O_CLOEXEC support, we
64  * are running on one without. */
65  if (errno != EINVAL)
66  return -1;
67 #endif /* defined(O_CLOEXEC) */
68 
69  log_debug(LD_FS, "Opening %s with flags %x", p, flags);
70  fd = open(p, flags, mode);
71 #ifdef FD_CLOEXEC
72  if (fd >= 0) {
73  if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
74  log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
75  close(fd);
76  return -1;
77  }
78  }
79 #endif /* defined(FD_CLOEXEC) */
80  return fd;
81 }
82 
85 FILE *
86 tor_fopen_cloexec(const char *path, const char *mode)
87 {
88  FILE *result = fopen(path, mode);
89 #ifdef FD_CLOEXEC
90  if (result != NULL) {
91  if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
92  log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
93  fclose(result);
94  return NULL;
95  }
96  }
97 #endif /* defined(FD_CLOEXEC) */
98  return result;
99 }
100 
102 int
103 tor_rename(const char *path_old, const char *path_new)
104 {
105  log_debug(LD_FS, "Renaming %s to %s", path_old, path_new);
106  return rename(sandbox_intern_string(path_old),
107  sandbox_intern_string(path_new));
108 }
109 
116 int
117 replace_file(const char *from, const char *to)
118 {
119 #ifndef _WIN32
120  return tor_rename(from, to);
121 #else
122  switch (file_status(to))
123  {
124  case FN_NOENT:
125  break;
126  case FN_FILE:
127  case FN_EMPTY:
128  if (unlink(to)) return -1;
129  break;
130  case FN_ERROR:
131  return -1;
132  case FN_DIR:
133  errno = EISDIR;
134  return -1;
135  }
136  return tor_rename(from,to);
137 #endif /* !defined(_WIN32) */
138 }
139 
141 int
142 touch_file(const char *fname)
143 {
144  if (utime(fname, NULL)!=0)
145  return -1;
146  return 0;
147 }
148 
153 MOCK_IMPL(int,
154 tor_unlink,(const char *pathname))
155 {
156  return unlink(pathname);
157 }
158 
161 ssize_t
162 write_all_to_fd(int fd, const char *buf, size_t count)
163 {
164  size_t written = 0;
165  ssize_t result;
166  raw_assert(count < SSIZE_MAX);
167 
168  while (written != count) {
169  result = write(fd, buf+written, count-written);
170  if (result<0)
171  return -1;
172  written += result;
173  }
174  return (ssize_t)count;
175 }
176 
180 ssize_t
181 read_all_from_fd(int fd, char *buf, size_t count)
182 {
183  size_t numread = 0;
184  ssize_t result;
185 
186  if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
187  errno = EINVAL;
188  return -1;
189  }
190 
191  while (numread < count) {
192  result = read(fd, buf+numread, count-numread);
193  if (result<0)
194  return -1;
195  else if (result == 0)
196  break;
197  numread += result;
198  }
199  return (ssize_t)numread;
200 }
201 
212 file_status(const char *fname)
213 {
214  struct stat st;
215  char *f;
216  int r;
217  if (!fname || strlen(fname) == 0) {
218  return FN_ERROR;
219  }
220  f = tor_strdup(fname);
222  log_debug(LD_FS, "stat()ing %s", f);
223  r = stat(sandbox_intern_string(f), &st);
224  tor_free(f);
225  if (r) {
226  if (errno == ENOENT) {
227  return FN_NOENT;
228  }
229  return FN_ERROR;
230  }
231  if (st.st_mode & S_IFDIR) {
232  return FN_DIR;
233  } else if (st.st_mode & S_IFREG) {
234  if (st.st_size > 0) {
235  return FN_FILE;
236  } else if (st.st_size == 0) {
237  return FN_EMPTY;
238  } else {
239  return FN_ERROR;
240  }
241 #ifndef _WIN32
242  } else if (st.st_mode & S_IFIFO) {
243  return FN_FILE;
244 #endif
245  } else {
246  return FN_ERROR;
247  }
248 }
249 
257 MOCK_IMPL(int,
258 write_str_to_file,(const char *fname, const char *str, int bin))
259 {
260 #ifdef _WIN32
261  if (!bin && strchr(str, '\r')) {
262  log_warn(LD_BUG,
263  "We're writing a text string that already contains a CR to %s",
264  escaped(fname));
265  }
266 #endif /* defined(_WIN32) */
267  return write_bytes_to_file(fname, str, strlen(str), bin);
268 }
269 
273 struct open_file_t {
274  char *tempname;
275  char *filename;
276  unsigned rename_on_close:1;
277  unsigned binary:1;
278  int fd;
279  FILE *stdio_file;
280 };
281 
300 int
301 start_writing_to_file(const char *fname, int open_flags, int mode,
302  open_file_t **data_out)
303 {
304  open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
305  const char *open_name;
306  int append = 0;
307 
308  tor_assert(fname);
309  tor_assert(data_out);
310 #if (O_BINARY != 0 && O_TEXT != 0)
311  tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
312 #endif
313  new_file->fd = -1;
314  new_file->filename = tor_strdup(fname);
315  if (open_flags & O_APPEND) {
316  open_name = fname;
317  new_file->rename_on_close = 0;
318  append = 1;
319  open_flags &= ~O_APPEND;
320  } else {
321  tor_asprintf(&new_file->tempname, "%s.tmp", fname);
322  open_name = new_file->tempname;
323  /* We always replace an existing temporary file if there is one. */
324  open_flags |= O_CREAT|O_TRUNC;
325  open_flags &= ~O_EXCL;
326  new_file->rename_on_close = 1;
327  }
328 #if O_BINARY != 0
329  if (open_flags & O_BINARY)
330  new_file->binary = 1;
331 #endif
332 
333  new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
334  if (new_file->fd < 0) {
335  log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
336  open_name, fname, strerror(errno));
337  goto err;
338  }
339  if (append) {
340  if (tor_fd_seekend(new_file->fd) < 0) {
341  log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
342  strerror(errno));
343  goto err;
344  }
345  }
346 
347  *data_out = new_file;
348 
349  return new_file->fd;
350 
351  err:
352  if (new_file->fd >= 0)
353  close(new_file->fd);
354  *data_out = NULL;
355  tor_free(new_file->filename);
356  tor_free(new_file->tempname);
357  tor_free(new_file);
358  return -1;
359 }
360 
364 FILE *
366 {
367  tor_assert(file_data);
368  if (file_data->stdio_file)
369  return file_data->stdio_file;
370  tor_assert(file_data->fd >= 0);
371  if (!(file_data->stdio_file = fdopen(file_data->fd,
372  file_data->binary?"ab":"a"))) {
373  log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
374  file_data->fd, strerror(errno));
375  }
376  return file_data->stdio_file;
377 }
378 
381 FILE *
382 start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
383  open_file_t **data_out)
384 {
385  FILE *res;
386  if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
387  return NULL;
388  if (!(res = fdopen_file(*data_out))) {
389  abort_writing_to_file(*data_out);
390  *data_out = NULL;
391  }
392  return res;
393 }
394 
399 static int
400 finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
401 {
402  int r = 0;
403 
404  tor_assert(file_data && file_data->filename);
405  if (file_data->stdio_file) {
406  if (fclose(file_data->stdio_file)) {
407  log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
408  strerror(errno));
409  abort_write = r = -1;
410  }
411  } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
412  log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
413  strerror(errno));
414  abort_write = r = -1;
415  }
416 
417  if (file_data->rename_on_close) {
418  tor_assert(file_data->tempname && file_data->filename);
419  if (!abort_write) {
420  tor_assert(strcmp(file_data->filename, file_data->tempname));
421  if (replace_file(file_data->tempname, file_data->filename)) {
422  log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
423  strerror(errno));
424  abort_write = r = -1;
425  }
426  }
427  if (abort_write) {
428  int res = unlink(file_data->tempname);
429  if (res != 0) {
430  /* We couldn't unlink and we'll leave a mess behind */
431  log_warn(LD_FS, "Failed to unlink %s: %s",
432  file_data->tempname, strerror(errno));
433  r = -1;
434  }
435  }
436  }
437 
438  tor_free(file_data->filename);
439  tor_free(file_data->tempname);
440  tor_free(file_data);
441 
442  return r;
443 }
444 
448 int
450 {
451  return finish_writing_to_file_impl(file_data, 0);
452 }
453 
456 int
458 {
459  return finish_writing_to_file_impl(file_data, 1);
460 }
461 
466 static int
467 write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
468  int open_flags)
469 {
470  open_file_t *file = NULL;
471  int fd;
472  ssize_t result;
473  fd = start_writing_to_file(fname, open_flags, 0600, &file);
474  if (fd<0)
475  return -1;
476  SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
477  {
478  result = write_all_to_fd(fd, chunk->bytes, chunk->len);
479  if (result < 0) {
480  log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
481  strerror(errno));
482  goto err;
483  }
484  tor_assert((size_t)result == chunk->len);
485  });
486 
487  return finish_writing_to_file(file);
488  err:
489  abort_writing_to_file(file);
490  return -1;
491 }
492 
497 int
498 write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin,
499  int no_tempfile)
500 {
501  int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
502 
503  if (no_tempfile) {
504  /* O_APPEND stops write_chunks_to_file from using tempfiles */
505  flags |= O_APPEND;
506  }
507  return write_chunks_to_file_impl(fname, chunks, flags);
508 }
509 
512 static int
513 write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
514  int flags)
515 {
516  int r;
517  sized_chunk_t c = { str, len };
518  smartlist_t *chunks = smartlist_new();
519  smartlist_add(chunks, &c);
520  r = write_chunks_to_file_impl(fname, chunks, flags);
521  smartlist_free(chunks);
522  return r;
523 }
524 
527 MOCK_IMPL(int,
528 write_bytes_to_file,(const char *fname, const char *str, size_t len,
529  int bin))
530 {
531  return write_bytes_to_file_impl(fname, str, len,
532  OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
533 }
534 
537 int
538 append_bytes_to_file(const char *fname, const char *str, size_t len,
539  int bin)
540 {
541  return write_bytes_to_file_impl(fname, str, len,
542  OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
543 }
544 
547 int
548 write_bytes_to_new_file(const char *fname, const char *str, size_t len,
549  int bin)
550 {
551  return write_bytes_to_file_impl(fname, str, len,
552  OPEN_FLAGS_DONT_REPLACE|
553  (bin?O_BINARY:O_TEXT));
554 }
555 
563 char *
564 read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
565 {
566  ssize_t r;
567  size_t pos = 0;
568  char *string = NULL;
569  size_t string_max = 0;
570 
571  if (max_bytes_to_read+1 >= SIZE_T_CEILING) {
572  errno = EINVAL;
573  return NULL;
574  }
575 
576  do {
577  /* XXXX This "add 1K" approach is a little goofy; if we care about
578  * performance here, we should be doubling. But in practice we shouldn't
579  * be using this function on big files anyway. */
580  string_max = pos + 1024;
581  if (string_max > max_bytes_to_read)
582  string_max = max_bytes_to_read + 1;
583  string = tor_realloc(string, string_max);
584  r = read(fd, string + pos, string_max - pos - 1);
585  if (r < 0) {
586  int save_errno = errno;
587  tor_free(string);
588  errno = save_errno;
589  return NULL;
590  }
591 
592  pos += r;
593  } while (r > 0 && pos < max_bytes_to_read);
594 
595  tor_assert(pos < string_max);
596  *sz_out = pos;
597  string[pos] = '\0';
598  return string;
599 }
600 
611 /*
612  * This function <em>may</em> return an erroneous result if the file
613  * is modified while it is running, but must not crash or overflow.
614  * Right now, the error case occurs when the file length grows between
615  * the call to stat and the call to read_all: the resulting string will
616  * be truncated.
617  */
618 MOCK_IMPL(char *,
619 read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
620 {
621  int fd; /* router file */
622  struct stat statbuf;
623  char *string;
624  ssize_t r;
625  int bin = flags & RFTS_BIN;
626 
627  tor_assert(filename);
628 
629  fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
630  if (fd<0) {
631  int severity = LOG_WARN;
632  int save_errno = errno;
633  if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
634  severity = LOG_INFO;
635  log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
636  strerror(errno));
637  errno = save_errno;
638  return NULL;
639  }
640 
641  if (fstat(fd, &statbuf)<0) {
642  int save_errno = errno;
643  close(fd);
644  log_warn(LD_FS,"Could not fstat \"%s\".",filename);
645  errno = save_errno;
646  return NULL;
647  }
648 
649 #ifndef _WIN32
650 
652 #define FIFO_READ_MAX (1024*1024)
653  if (S_ISFIFO(statbuf.st_mode)) {
654  size_t sz = 0;
655  string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
656  int save_errno = errno;
657  if (string && stat_out) {
658  statbuf.st_size = sz;
659  memcpy(stat_out, &statbuf, sizeof(struct stat));
660  }
661  close(fd);
662  if (!string)
663  errno = save_errno;
664  return string;
665  }
666 #endif /* !defined(_WIN32) */
667 
668  if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
669  close(fd);
670  errno = EINVAL;
671  return NULL;
672  }
673 
674  string = tor_malloc((size_t)(statbuf.st_size+1));
675 
676  r = read_all_from_fd(fd,string,(size_t)statbuf.st_size);
677  if (r<0) {
678  int save_errno = errno;
679  log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
680  strerror(errno));
681  tor_free(string);
682  close(fd);
683  errno = save_errno;
684  return NULL;
685  }
686  string[r] = '\0'; /* NUL-terminate the result. */
687 
688 #if defined(_WIN32) || defined(__CYGWIN__)
689  if (!bin && strchr(string, '\r')) {
690  log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
691  "when reading %s. Coping.",
692  filename);
693  tor_strstrip(string, "\r");
694  r = strlen(string);
695  }
696  if (!bin) {
697  statbuf.st_size = (size_t) r;
698  } else
699 #endif /* defined(_WIN32) || defined(__CYGWIN__) */
700  if (r != statbuf.st_size) {
701  /* Unless we're using text mode on win32, we'd better have an exact
702  * match for size. */
703  int save_errno = errno;
704  log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
705  (int)r, (long)statbuf.st_size,filename);
706  tor_free(string);
707  close(fd);
708  errno = save_errno;
709  return NULL;
710  }
711  close(fd);
712  if (stat_out) {
713  memcpy(stat_out, &statbuf, sizeof(struct stat));
714  }
715 
716  return string;
717 }
718 
719 #if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS)
720 #include "ext/getdelim.c"
721 #endif
FILE * stdio_file
Definition: files.c:279
Header for printf.c.
Header for smartlist.c.
int tor_open_cloexec(const char *path, int flags, unsigned mode)
Definition: files.c:54
int tor_fd_seekend(int fd)
Definition: fdio.c:60
int replace_file(const char *from, const char *to)
Definition: files.c:117
int write_bytes_to_new_file(const char *fname, const char *str, size_t len, int bin)
Definition: files.c:548
#define LOG_INFO
Definition: log.h:43
Header for fdio.c.
void smartlist_add(smartlist_t *sl, void *element)
int fd
Definition: files.c:278
void tor_strstrip(char *s, const char *strip)
Definition: util_string.c:111
ssize_t write_all_to_fd(int fd, const char *buf, size_t count)
Definition: files.c:162
FILE * fdopen_file(open_file_t *file_data)
Definition: files.c:365
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
Headers for util_malloc.c.
void clean_fname_for_stat(char *name)
Definition: path.c:145
#define sandbox_intern_string(s)
Definition: sandbox.h:112
char * filename
Definition: files.c:275
char * tempname
Definition: files.c:274
FILE * start_writing_to_stdio_file(const char *fname, int open_flags, int mode, open_file_t **data_out)
Definition: files.c:382
tor_assert(buffer)
int append_bytes_to_file(const char *fname, const char *str, size_t len, int bin)
Definition: files.c:538
int finish_writing_to_file(open_file_t *file_data)
Definition: files.c:449
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
#define SIZE_T_CEILING
Definition: torint.h:126
Header file for sandbox.c.
#define LOG_WARN
Definition: log.h:51
#define RFTS_IGNORE_MISSING
Definition: files.h:97
int start_writing_to_file(const char *fname, int open_flags, int mode, open_file_t **data_out)
Definition: files.c:301
#define LD_FS
Definition: log.h:68
Header for path.c.
char * read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) ATTR_MALLOC
Definition: files.c:564
unsigned binary
Definition: files.c:277
ssize_t read_all_from_fd(int fd, char *buf, size_t count)
Definition: files.c:181
#define RFTS_BIN
Definition: files.h:95
#define SMARTLIST_FOREACH(sl, type, var, cmd)
const char * escaped(const char *s)
Definition: escape.c:126
file_status_t
Definition: files.h:55
#define log_fn(severity, domain, args,...)
Definition: log.h:274
Header for escape.c.
Wrappers for reading and writing data to files on disk.
Headers for torerr.c.
unsigned rename_on_close
Definition: files.c:276
int abort_writing_to_file(open_file_t *file_data)
Definition: files.c:457
Headers for log.c.
int tor_rename(const char *path_old, const char *path_new)
Definition: files.c:103
Macros to manage assertions, fatal and non-fatal.
FILE * tor_fopen_cloexec(const char *path, const char *mode)
Definition: files.c:86
file_status_t file_status(const char *filename)
Definition: files.c:212
#define LD_BUG
Definition: log.h:84
int touch_file(const char *fname)
Definition: files.c:142