Tor 0.4.9.0-alpha-dev
files.c
1/* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file files.h
8 *
9 * \brief Wrappers for reading and writing data to files on disk.
10 **/
11
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"
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
51/** As open(path, flags, mode), but return an fd with the close-on-exec mode
52 * set. */
53int
54tor_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
83/** As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the
84 * underlying file handle. */
85FILE *
86tor_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
101/** As rename(), but work correctly with the sandbox. */
102int
103tor_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
110/**
111 * Rename the file <b>from</b> to the file <b>to</b>. On Unix, this is
112 * the same as rename(2). On windows, this removes <b>to</b> first if
113 * it already exists.
114 * Returns 0 on success. Returns -1 and sets errno on failure.
115 */
116int
117replace_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
140/** Change <b>fname</b>'s modification time to now. */
141int
142touch_file(const char *fname)
143{
144 if (utime(fname, NULL)!=0)
145 return -1;
146 return 0;
147}
148
149/** Wrapper for unlink() to make it mockable for the test suite; returns 0
150 * if unlinking the file succeeded, -1 and sets errno if unlinking fails.
151 */
152
153MOCK_IMPL(int,
154tor_unlink,(const char *pathname))
155{
156 return unlink(pathname);
157}
158
159/** Write <b>count</b> bytes from <b>buf</b> to <b>fd</b>. Return the number
160 * of bytes written, or -1 on error. Only use if fd is a blocking fd. */
161ssize_t
162write_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
177/** Read from <b>fd</b> to <b>buf</b>, until we get <b>count</b> bytes or
178 * reach the end of the file. Return the number of bytes read, or -1 on
179 * error. Only use if fd is a blocking fd. */
180ssize_t
181read_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
202/** Return:
203 * FN_ERROR if filename can't be read, is NULL, or is zero-length,
204 * FN_NOENT if it doesn't exist,
205 * FN_FILE if it is a non-empty regular file, or a FIFO on unix-like systems,
206 * FN_EMPTY for zero-byte regular files,
207 * FN_DIR if it's a directory, and
208 * FN_ERROR for any other file type.
209 * On FN_ERROR and FN_NOENT, sets errno. (errno is not set when FN_ERROR
210 * is returned due to an unhandled file type.) */
212file_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
250/** Returns true if <b>file_type</b> represents an existing file (even if
251 * empty). Returns false otherwise. */
252bool
254{
255 return file_type != FN_ERROR && file_type != FN_NOENT && file_type != FN_DIR;
256}
257
258/** Returns true if <b>file_type</b> represents an existing directory. Returns
259 * false otherwise. */
260bool
262{
263 return file_type == FN_DIR;
264}
265
266/** Create a file named <b>fname</b> with the contents <b>str</b>. Overwrite
267 * the previous <b>fname</b> if possible. Return 0 on success, -1 on failure.
268 *
269 * This function replaces the old file atomically, if possible. This
270 * function, and all other functions in util.c that create files, create them
271 * with mode 0600.
272 */
273MOCK_IMPL(int,
274write_str_to_file,(const char *fname, const char *str, int bin))
275{
276#ifdef _WIN32
277 if (!bin && strchr(str, '\r')) {
278 log_warn(LD_BUG,
279 "We're writing a text string that already contains a CR to %s",
280 escaped(fname));
281 }
282#endif /* defined(_WIN32) */
283 return write_bytes_to_file(fname, str, strlen(str), bin);
284}
285
286/** Represents a file that we're writing to, with support for atomic commit:
287 * we can write into a temporary file, and either remove the file on
288 * failure, or replace the original file on success. */
290 char *tempname; /**< Name of the temporary file. */
291 char *filename; /**< Name of the original file. */
292 unsigned rename_on_close:1; /**< Are we using the temporary file or not? */
293 unsigned binary:1; /**< Did we open in binary mode? */
294 int fd; /**< fd for the open file. */
295 FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */
296};
297
298/** Try to start writing to the file in <b>fname</b>, passing the flags
299 * <b>open_flags</b> to the open() syscall, creating the file (if needed) with
300 * access value <b>mode</b>. If the O_APPEND flag is set, we append to the
301 * original file. Otherwise, we open a new temporary file in the same
302 * directory, and either replace the original or remove the temporary file
303 * when we're done.
304 *
305 * Return the fd for the newly opened file, and store working data in
306 * *<b>data_out</b>. The caller should not close the fd manually:
307 * instead, call finish_writing_to_file() or abort_writing_to_file().
308 * Returns -1 on failure.
309 *
310 * NOTE: When not appending, the flags O_CREAT and O_TRUNC are treated
311 * as true and the flag O_EXCL is treated as false.
312 *
313 * NOTE: Ordinarily, O_APPEND means "seek to the end of the file before each
314 * write()". We don't do that.
315 */
316int
317start_writing_to_file(const char *fname, int open_flags, int mode,
318 open_file_t **data_out)
319{
320 open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
321 const char *open_name;
322 int append = 0;
323
324 tor_assert(fname);
325 tor_assert(data_out);
326#if (O_BINARY != 0 && O_TEXT != 0)
327 tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
328#endif
329 new_file->fd = -1;
330 new_file->filename = tor_strdup(fname);
331 if (open_flags & O_APPEND) {
332 open_name = fname;
333 new_file->rename_on_close = 0;
334 append = 1;
335 open_flags &= ~O_APPEND;
336 } else {
337 tor_asprintf(&new_file->tempname, "%s.tmp", fname);
338 open_name = new_file->tempname;
339 /* We always replace an existing temporary file if there is one. */
340 open_flags |= O_CREAT|O_TRUNC;
341 open_flags &= ~O_EXCL;
342 new_file->rename_on_close = 1;
343 }
344#if O_BINARY != 0
345 if (open_flags & O_BINARY)
346 new_file->binary = 1;
347#endif
348
349 new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
350 if (new_file->fd < 0) {
351 log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
352 open_name, fname, strerror(errno));
353 goto err;
354 }
355 if (append) {
356 if (tor_fd_seekend(new_file->fd) < 0) {
357 log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
358 strerror(errno));
359 goto err;
360 }
361 }
362
363 *data_out = new_file;
364
365 return new_file->fd;
366
367 err:
368 if (new_file->fd >= 0)
369 close(new_file->fd);
370 *data_out = NULL;
371 tor_free(new_file->filename);
372 tor_free(new_file->tempname);
373 tor_free(new_file);
374 return -1;
375}
376
377/** Given <b>file_data</b> from start_writing_to_file(), return a stdio FILE*
378 * that can be used to write to the same file. The caller should not mix
379 * stdio calls with non-stdio calls. */
380FILE *
382{
383 tor_assert(file_data);
384 if (file_data->stdio_file)
385 return file_data->stdio_file;
386 tor_assert(file_data->fd >= 0);
387 if (!(file_data->stdio_file = fdopen(file_data->fd,
388 file_data->binary?"ab":"a"))) {
389 log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
390 file_data->fd, strerror(errno));
391 }
392 return file_data->stdio_file;
393}
394
395/** Combines start_writing_to_file with fdopen_file(): arguments are as
396 * for start_writing_to_file, but */
397FILE *
398start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
399 open_file_t **data_out)
400{
401 FILE *res;
402 if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
403 return NULL;
404 if (!(res = fdopen_file(*data_out))) {
405 abort_writing_to_file(*data_out);
406 *data_out = NULL;
407 }
408 return res;
409}
410
411/** Helper function: close and free the underlying file and memory in
412 * <b>file_data</b>. If we were writing into a temporary file, then delete
413 * that file (if abort_write is true) or replaces the target file with
414 * the temporary file (if abort_write is false). */
415static int
416finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
417{
418 int r = 0;
419
420 tor_assert(file_data && file_data->filename);
421 if (file_data->stdio_file) {
422 if (fclose(file_data->stdio_file)) {
423 log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
424 strerror(errno));
425 abort_write = r = -1;
426 }
427 } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
428 log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
429 strerror(errno));
430 abort_write = r = -1;
431 }
432
433 if (file_data->rename_on_close) {
434 tor_assert(file_data->tempname && file_data->filename);
435 if (!abort_write) {
436 tor_assert(strcmp(file_data->filename, file_data->tempname));
437 if (replace_file(file_data->tempname, file_data->filename)) {
438 log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
439 strerror(errno));
440 abort_write = r = -1;
441 }
442 }
443 if (abort_write) {
444 int res = unlink(file_data->tempname);
445 if (res != 0) {
446 /* We couldn't unlink and we'll leave a mess behind */
447 log_warn(LD_FS, "Failed to unlink %s: %s",
448 file_data->tempname, strerror(errno));
449 r = -1;
450 }
451 }
452 }
453
454 tor_free(file_data->filename);
455 tor_free(file_data->tempname);
456 tor_free(file_data);
457
458 return r;
459}
460
461/** Finish writing to <b>file_data</b>: close the file handle, free memory as
462 * needed, and if using a temporary file, replace the original file with
463 * the temporary file. */
464int
466{
467 return finish_writing_to_file_impl(file_data, 0);
468}
469
470/** Finish writing to <b>file_data</b>: close the file handle, free memory as
471 * needed, and if using a temporary file, delete it. */
472int
474{
475 return finish_writing_to_file_impl(file_data, 1);
476}
477
478/** Helper: given a set of flags as passed to open(2), open the file
479 * <b>fname</b> and write all the sized_chunk_t structs in <b>chunks</b> to
480 * the file. Do so as atomically as possible e.g. by opening temp files and
481 * renaming. */
482static int
483write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
484 int open_flags)
485{
486 open_file_t *file = NULL;
487 int fd;
488 ssize_t result;
489 fd = start_writing_to_file(fname, open_flags, 0600, &file);
490 if (fd<0)
491 return -1;
492 SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
493 {
494 result = write_all_to_fd(fd, chunk->bytes, chunk->len);
495 if (result < 0) {
496 log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
497 strerror(errno));
498 goto err;
499 }
500 tor_assert((size_t)result == chunk->len);
501 });
502
503 return finish_writing_to_file(file);
504 err:
506 return -1;
507}
508
509/** Given a smartlist of sized_chunk_t, write them to a file
510 * <b>fname</b>, overwriting or creating the file as necessary.
511 * If <b>no_tempfile</b> is 0 then the file will be written
512 * atomically. */
513int
514write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin,
515 int no_tempfile)
516{
517 int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
518
519 if (no_tempfile) {
520 /* O_APPEND stops write_chunks_to_file from using tempfiles */
521 flags |= O_APPEND;
522 }
523 return write_chunks_to_file_impl(fname, chunks, flags);
524}
525
526/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
527 using the open() flags passed in <b>flags</b>. */
528static int
529write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
530 int flags)
531{
532 int r;
533 sized_chunk_t c = { str, len };
534 smartlist_t *chunks = smartlist_new();
535 smartlist_add(chunks, &c);
536 r = write_chunks_to_file_impl(fname, chunks, flags);
537 smartlist_free(chunks);
538 return r;
539}
540
541/** As write_str_to_file, but does not assume a NUL-terminated
542 * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
543MOCK_IMPL(int,
544write_bytes_to_file,(const char *fname, const char *str, size_t len,
545 int bin))
546{
547 return write_bytes_to_file_impl(fname, str, len,
548 OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
549}
550
551/** As write_bytes_to_file, but if the file already exists, append the bytes
552 * to the end of the file instead of overwriting it. */
553int
554append_bytes_to_file(const char *fname, const char *str, size_t len,
555 int bin)
556{
557 return write_bytes_to_file_impl(fname, str, len,
558 OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
559}
560
561/** Like write_str_to_file(), but also return -1 if there was a file
562 already residing in <b>fname</b>. */
563int
564write_bytes_to_new_file(const char *fname, const char *str, size_t len,
565 int bin)
566{
567 return write_bytes_to_file_impl(fname, str, len,
568 OPEN_FLAGS_DONT_REPLACE|
569 (bin?O_BINARY:O_TEXT));
570}
571
572/**
573 * Read the contents of the open file <b>fd</b> presuming it is a FIFO
574 * (or similar) file descriptor for which the size of the file isn't
575 * known ahead of time. Return NULL on failure, and a NUL-terminated
576 * string on success. On success, set <b>sz_out</b> to the number of
577 * bytes read.
578 */
579char *
580read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
581{
582 ssize_t r;
583 size_t pos = 0;
584 char *string = NULL;
585 size_t string_max = 0;
586
587 if (max_bytes_to_read+1 >= SIZE_T_CEILING) {
588 errno = EINVAL;
589 return NULL;
590 }
591
592 do {
593 /* XXXX This "add 1K" approach is a little goofy; if we care about
594 * performance here, we should be doubling. But in practice we shouldn't
595 * be using this function on big files anyway. */
596 string_max = pos + 1024;
597 if (string_max > max_bytes_to_read)
598 string_max = max_bytes_to_read + 1;
599 string = tor_realloc(string, string_max);
600 r = read(fd, string + pos, string_max - pos - 1);
601 if (r < 0) {
602 int save_errno = errno;
603 tor_free(string);
604 errno = save_errno;
605 return NULL;
606 }
607
608 pos += r;
609 } while (r > 0 && pos < max_bytes_to_read);
610
611 tor_assert(pos < string_max);
612 *sz_out = pos;
613 string[pos] = '\0';
614 return string;
615}
616
617/** Read the contents of <b>filename</b> into a newly allocated
618 * string; return the string on success or NULL on failure.
619 *
620 * If <b>stat_out</b> is provided, store the result of stat()ing the
621 * file into <b>stat_out</b>.
622 *
623 * If <b>flags</b> &amp; RFTS_BIN, open the file in binary mode.
624 * If <b>flags</b> &amp; RFTS_IGNORE_MISSING, don't warn if the file
625 * doesn't exist.
626 *
627 * Unless the RFTS_BIN flag is set in <b>flags</b>, this function will strip
628 * any CR characters in the return value on all platforms.
629 */
630/*
631 * This function <em>may</em> return an erroneous result if the file
632 * is modified while it is running, but must not crash or overflow.
633 * Right now, the error case occurs when the file length grows between
634 * the call to stat and the call to read_all: the resulting string will
635 * be truncated.
636 */
637MOCK_IMPL(char *,
638read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
639{
640 int fd; /* router file */
641 struct stat statbuf;
642 char *string;
643 ssize_t r;
644 int bin = flags & RFTS_BIN;
645
646 tor_assert(filename);
647
648 fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
649 if (fd<0) {
650 int severity = LOG_WARN;
651 int save_errno = errno;
652 if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
653 severity = LOG_INFO;
654 log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
655 strerror(errno));
656 errno = save_errno;
657 return NULL;
658 }
659
660 if (fstat(fd, &statbuf)<0) {
661 int save_errno = errno;
662 close(fd);
663 log_warn(LD_FS,"Could not fstat \"%s\".",filename);
664 errno = save_errno;
665 return NULL;
666 }
667
668#ifndef _WIN32
669/** When we detect that we're reading from a FIFO, don't read more than
670 * this many bytes. It's insane overkill for most uses. */
671#define FIFO_READ_MAX (1024*1024)
672 if (S_ISFIFO(statbuf.st_mode)) {
673 size_t sz = 0;
674 string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
675 int save_errno = errno;
676 if (string && stat_out) {
677 statbuf.st_size = sz;
678 memcpy(stat_out, &statbuf, sizeof(struct stat));
679 }
680 close(fd);
681 if (!string)
682 errno = save_errno;
683 return string;
684 }
685#endif /* !defined(_WIN32) */
686
687 if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
688 close(fd);
689 errno = EINVAL;
690 return NULL;
691 }
692
693 string = tor_malloc((size_t)(statbuf.st_size+1));
694
695 r = read_all_from_fd(fd,string,(size_t)statbuf.st_size);
696 if (r<0) {
697 int save_errno = errno;
698 log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
699 strerror(errno));
700 tor_free(string);
701 close(fd);
702 errno = save_errno;
703 return NULL;
704 }
705 string[r] = '\0'; /* NUL-terminate the result. */
706
707 if (!bin && strchr(string, '\r')) {
708 log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
709 "when reading %s. Coping.",
710 filename);
711 tor_strstrip(string, "\r");
712 r = strlen(string);
713 }
714 if (!bin) {
715 statbuf.st_size = (size_t) r;
716 } else {
717 if (r != statbuf.st_size) {
718 /* Unless we're using text mode on win32, we'd better have an exact
719 * match for size. */
720 int save_errno = errno;
721 log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
722 (int)r, (long)statbuf.st_size,filename);
723 tor_free(string);
724 close(fd);
725 errno = save_errno;
726 return NULL;
727 }
728 }
729 close(fd);
730 if (stat_out) {
731 memcpy(stat_out, &statbuf, sizeof(struct stat));
732 }
733
734 return string;
735}
736
737/** Attempt to read a file <b>fname</b>. If the file's contents is
738 * equal to the string <b>str</b>, return 0. Otherwise, attempt to
739 * overwrite the file with the contents of <b>str</b> and return
740 * the value of write_str_to_file().
741 */
742int
743write_str_to_file_if_not_equal(const char *fname, const char *str)
744{
745 char *fstr = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
746 int rv;
747
748 if (!fstr || strcmp(str, fstr)) {
749 rv = write_str_to_file(fname, str, 0);
750 } else {
751 rv = 0;
752 }
753 tor_free(fstr);
754 return rv;
755}
756
757#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS)
758#include "ext/getdelim.c"
759#endif
const char * escaped(const char *s)
Definition: escape.c:126
Header for escape.c.
int tor_fd_seekend(int fd)
Definition: fdio.c:61
Header for fdio.c.
Wrappers for reading and writing data to files on disk.
char * read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) ATTR_MALLOC
Definition: files.c:580
int write_str_to_file(const char *fname, const char *str, int bin)
Definition: files.c:274
ssize_t read_all_from_fd(int fd, char *buf, size_t count)
Definition: files.c:181
int tor_unlink(const char *pathname)
Definition: files.c:154
#define RFTS_IGNORE_MISSING
Definition: files.h:101
file_status_t file_status(const char *filename)
Definition: files.c:212
int finish_writing_to_file(open_file_t *file_data)
Definition: files.c:465
int write_bytes_to_new_file(const char *fname, const char *str, size_t len, int bin)
Definition: files.c:564
int start_writing_to_file(const char *fname, int open_flags, int mode, open_file_t **data_out)
Definition: files.c:317
int tor_open_cloexec(const char *path, int flags, unsigned mode)
Definition: files.c:54
int touch_file(const char *fname)
Definition: files.c:142
ssize_t write_all_to_fd(int fd, const char *buf, size_t count)
Definition: files.c:162
int write_str_to_file_if_not_equal(const char *fname, const char *str)
Definition: files.c:743
file_status_t
Definition: files.h:55
int append_bytes_to_file(const char *fname, const char *str, size_t len, int bin)
Definition: files.c:554
FILE * start_writing_to_stdio_file(const char *fname, int open_flags, int mode, open_file_t **data_out)
Definition: files.c:398
int replace_file(const char *from, const char *to)
Definition: files.c:117
int abort_writing_to_file(open_file_t *file_data)
Definition: files.c:473
int write_bytes_to_file(const char *fname, const char *str, size_t len, int bin)
Definition: files.c:545
FILE * tor_fopen_cloexec(const char *path, const char *mode)
Definition: files.c:86
#define RFTS_BIN
Definition: files.h:99
int tor_rename(const char *path_old, const char *path_new)
Definition: files.c:103
bool is_file(file_status_t file_type)
Definition: files.c:253
FILE * fdopen_file(open_file_t *file_data)
Definition: files.c:381
bool is_dir(file_status_t file_type)
Definition: files.c:261
Headers for log.c.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_FS
Definition: log.h:70
#define LD_BUG
Definition: log.h:86
#define LOG_WARN
Definition: log.h:53
#define LOG_INFO
Definition: log.h:45
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
void clean_fname_for_stat(char *name)
Definition: path.c:164
Header for path.c.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
Header for printf.c.
Header file for sandbox.c.
#define sandbox_intern_string(s)
Definition: sandbox.h:110
Header for smartlist.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
unsigned rename_on_close
Definition: files.c:292
int fd
Definition: files.c:294
FILE * stdio_file
Definition: files.c:295
unsigned binary
Definition: files.c:293
char * tempname
Definition: files.c:290
char * filename
Definition: files.c:291
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Headers for torerr.c.
#define SIZE_T_CEILING
Definition: torint.h:126
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103
void tor_strstrip(char *s, const char *strip)
Definition: util_string.c:113
Header for util_string.c.