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