TR181-XPON  1.4.0
TR-181 PON manager.
file_utils.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or
8 ** without modification, are permitted provided that the following
9 ** conditions are met:
10 **
11 ** 1. Redistributions of source code must retain the above copyright
12 ** notice, this list of conditions and the following disclaimer.
13 **
14 ** 2. Redistributions in binary form must reproduce the above
15 ** copyright notice, this list of conditions and the following
16 ** disclaimer in the documentation and/or other materials provided
17 ** with the distribution.
18 **
19 ** Subject to the terms and conditions of this license, each
20 ** copyright holder and contributor hereby grants to those receiving
21 ** rights under this license a perpetual, worldwide, non-exclusive,
22 ** no-charge, royalty-free, irrevocable (except for failure to
23 ** satisfy the conditions of this license) patent license to make,
24 ** have made, use, offer to sell, sell, import, and otherwise
25 ** transfer this software, where such license applies only to those
26 ** patent claims, already acquired or hereafter acquired, licensable
27 ** by such copyright holder or contributor that are necessarily
28 ** infringed by:
29 **
30 ** (a) their Contribution(s) (the licensed copyrights of copyright
31 ** holders and non-copyrightable additions of contributors, in
32 ** source or binary form) alone; or
33 **
34 ** (b) combination of their Contribution(s) with the work of
35 ** authorship to which such Contribution(s) was added by such
36 ** copyright holder or contributor, if, at the time the Contribution
37 ** is added, such addition causes such combination to be necessarily
38 ** infringed. The patent license shall not apply to any other
39 ** combinations which include the Contribution.
40 **
41 ** Except as expressly stated above, no rights or licenses from any
42 ** copyright holder or contributor is granted under this license,
43 ** whether expressly, by implication, estoppel or otherwise.
44 **
45 ** DISCLAIMER
46 **
47 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
48 ** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
49 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
50 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
52 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
55 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
56 ** AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
58 ** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 ** POSSIBILITY OF SUCH DAMAGE.
60 **
61 ****************************************************************************/
62 
63 /* Related header */
64 #include "file_utils.h"
65 
70 #ifndef _GNU_SOURCE
71 #define _GNU_SOURCE
72 #endif
73 
74 /* System headers */
75 #include <errno.h>
76 #include <fcntl.h> /* open() */
77 #include <stdio.h> /* rename() */
78 #include <string.h> /* strerror() */
79 #include <unistd.h> /* fdatasync() */
80 
81 /* Own headers */
82 #include "xpon_trace.h"
83 
84 #define LINE_LEN 256
85 
86 static bool rename_file(const char* const oldpath, const char* const newpath) {
87  int fd = 0;
88  if(rename(oldpath, newpath) == -1) {
89  SAH_TRACEZ_ERROR(ME, "Failed to rename %s to %s: %s", oldpath, newpath,
90  strerror(errno));
91  return false;
92  }
93  if((fd = open(newpath, O_RDWR)) == -1) {
94  SAH_TRACEZ_ERROR(ME, "Failed to open %s: %s", newpath, strerror(errno));
95  return false;
96  }
97  if(fdatasync(fd) == -1) {
98  SAH_TRACEZ_ERROR(ME, "Failed to sync %s: %s", newpath, strerror(errno));
99  }
100  close(fd);
101  return true;
102 }
103 
114 static bool check_file_has_value(const char* const path, const char* const value,
115  bool* has_value) {
116 
117  char line[LINE_LEN] = { 0 };
118  if(!read_first_line_from_file(path, line, LINE_LEN)) {
119  return false;
120  }
121  SAH_TRACEZ_DEBUG2(ME, "line='%s' (%zd) value='%s' (%zd)", line, strlen(line),
122  value, strlen(value));
123 
124  const size_t line_len = strlen(line);
125  const size_t value_len = strlen(value);
126  if(line_len != value_len) {
127  *has_value = false;
128  return true;
129  }
130 
131  if(strncmp(line, value, strlen(value)) == 0) {
132  SAH_TRACEZ_DEBUG2(ME, "file already has %s", value);
133  *has_value = true;
134  } else {
135  SAH_TRACEZ_DEBUG2(ME, "line='%s' != value='%s'", line, value);
136  }
137  return true;
138 }
139 
154 bool write_file(const char* const path, const char* const value) {
155 
156  SAH_TRACEZ_DEBUG2(ME, "path='%s' value='%s'", path, value);
157 
158  const size_t value_len = strlen(value);
159  if(value_len >= LINE_LEN) {
160  SAH_TRACEZ_ERROR(ME, "strlen(value) = %zd >= %d", value_len, LINE_LEN);
161  return false;
162  }
167  if(access(path, F_OK) == 0) {
168  SAH_TRACEZ_DEBUG2(ME, "%s already exists", path);
169  bool has_value = false;
170  if((check_file_has_value(path, value, &has_value) == true) && has_value) {
171  return true;
172  }
173  }
174 
175  char tmpfile[256];
176  if(snprintf(tmpfile, 256, "%s.tmp", path) < 0) {
177  SAH_TRACEZ_ERROR(ME, "%s: failed to create path with .tmp", path);
178  return false;
179  }
180 
181  FILE* f = fopen(tmpfile, "w");
182  if(!f) {
183  SAH_TRACEZ_ERROR(ME, "Failed to open %s: %s", tmpfile, strerror(errno));
184  return false;
185  }
186 
187  bool rv = true;
188  if(fputs(value, f) == EOF) {
189  SAH_TRACEZ_ERROR(ME, "Failed to write to %s", tmpfile);
190  rv = false;
191  }
192 
193  if(fclose(f) == EOF) {
194  SAH_TRACEZ_ERROR(ME, "Failed to close %s: %s", tmpfile, strerror(errno));
195  }
196  if(!rv) {
197  return false;
198  }
199  return rename_file(tmpfile, path);
200 }
201 
212 bool read_first_line_from_file(const char* const path, char* line, size_t len) {
213  FILE* f = fopen(path, "r");
214  if(!f) {
215  SAH_TRACEZ_ERROR(ME, "Failed to open %s: %s", path, strerror(errno));
216  return false;
217  }
218  bool rv = true;
219  if(!fgets(line, (int) len, f)) {
220  SAH_TRACEZ_ERROR(ME, "Failed to read from %s", path);
221  rv = false;
222  }
223  if(fclose(f) == EOF) {
224  SAH_TRACEZ_ERROR(ME, "Failed to close %s: %s", path, strerror(errno));
225  }
226  return rv;
227 }
228 
static bool check_file_has_value(const char *const path, const char *const value, bool *has_value)
Definition: file_utils.c:114
#define LINE_LEN
Definition: file_utils.c:84
bool write_file(const char *const path, const char *const value)
Definition: file_utils.c:154
bool read_first_line_from_file(const char *const path, char *line, size_t len)
Definition: file_utils.c:212
static bool rename_file(const char *const oldpath, const char *const newpath)
Definition: file_utils.c:86
#define SAH_TRACEZ_DEBUG2(zone, format,...)
Definition: xpon_trace.h:127
#define ME
Definition: xpon_trace.h:78