1 | #include "globals.h"
|
---|
2 |
|
---|
3 | #include "oscam-files.h"
|
---|
4 | #include "oscam-lock.h"
|
---|
5 | #include "oscam-string.h"
|
---|
6 |
|
---|
7 | extern CS_MUTEX_LOCK readdir_lock;
|
---|
8 | extern char cs_tmpdir[200];
|
---|
9 |
|
---|
10 | /* Gets the tmp dir */
|
---|
11 | char *get_tmp_dir(void) {
|
---|
12 | if (cs_tmpdir[0])
|
---|
13 | return cs_tmpdir;
|
---|
14 | #if defined(__CYGWIN__)
|
---|
15 | char *d = getenv("TMPDIR");
|
---|
16 | if (!d || !d[0])
|
---|
17 | d = getenv("TMP");
|
---|
18 | if (!d || !d[0])
|
---|
19 | d = getenv("TEMP");
|
---|
20 | if (!d || !d[0])
|
---|
21 | getcwd(cs_tmpdir, sizeof(cs_tmpdir)-1);
|
---|
22 |
|
---|
23 | cs_strncpy(cs_tmpdir, d, sizeof(cs_tmpdir));
|
---|
24 | char *p = cs_tmpdir;
|
---|
25 | while(*p) p++;
|
---|
26 | p--;
|
---|
27 | if (*p != '/' && *p != '\\')
|
---|
28 | strcat(cs_tmpdir, "/");
|
---|
29 | strcat(cs_tmpdir, "_oscam");
|
---|
30 | #else
|
---|
31 | cs_strncpy(cs_tmpdir, "/tmp/.oscam", sizeof(cs_tmpdir));
|
---|
32 | #endif
|
---|
33 | mkdir(cs_tmpdir, S_IRWXU);
|
---|
34 | return cs_tmpdir;
|
---|
35 | }
|
---|
36 |
|
---|
37 | char *get_tmp_dir_filename(char *dest, size_t destlen, const char *filename) {
|
---|
38 | char *tmp_dir = get_tmp_dir();
|
---|
39 | const char *slash = "/";
|
---|
40 | if (tmp_dir[strlen(tmp_dir) - 1] == '/') slash = "";
|
---|
41 | snprintf(dest, destlen, "%s%s%s", tmp_dir, slash, filename);
|
---|
42 | return dest;
|
---|
43 | }
|
---|
44 |
|
---|
45 | /* Drop-in replacement for readdir_r as some plattforms strip the function from their libc.
|
---|
46 | Furthermore, there are some security issues, see http://womble.decadent.org.uk/readdir_r-advisory.html */
|
---|
47 | int32_t cs_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
|
---|
48 | /* According to POSIX the buffer readdir uses is not shared between directory streams.
|
---|
49 | However readdir is not guaranteed to be thread-safe and some implementations may use global state.
|
---|
50 | Thus we use a lock as we have many plattforms... */
|
---|
51 | int32_t rc;
|
---|
52 | cs_writelock(&readdir_lock);
|
---|
53 | errno = 0;
|
---|
54 | *result = readdir(dirp);
|
---|
55 | rc = errno;
|
---|
56 | if (errno == 0 && *result != NULL) {
|
---|
57 | memcpy(entry, *result, sizeof(struct dirent));
|
---|
58 | *result = entry;
|
---|
59 | }
|
---|
60 | cs_writeunlock(&readdir_lock);
|
---|
61 | return rc;
|
---|
62 | }
|
---|
63 |
|
---|
64 | /* Return 1 if the file exists, else 0 */
|
---|
65 | bool file_exists(const char *filename) {
|
---|
66 | return access(filename, R_OK) == 0;
|
---|
67 | }
|
---|
68 |
|
---|
69 | /* Copies a file from srcfile to destfile. If an error occured before writing, -1 is returned, else -2. On success, 0 is returned.*/
|
---|
70 | int32_t file_copy(char *srcfile, char *destfile) {
|
---|
71 | FILE *src, *dest;
|
---|
72 | int32_t ch;
|
---|
73 | src = fopen(srcfile, "r");
|
---|
74 | if (!src) {
|
---|
75 | cs_log("Error opening file %s for reading (errno=%d %s)!", srcfile, errno, strerror(errno));
|
---|
76 | return -1;
|
---|
77 | }
|
---|
78 | dest = fopen(destfile, "w");
|
---|
79 | if (!dest) {
|
---|
80 | cs_log("Error opening file %s for writing (errno=%d %s)!", destfile, errno, strerror(errno));
|
---|
81 | fclose(src);
|
---|
82 | return -1;
|
---|
83 | }
|
---|
84 | while(1) {
|
---|
85 | ch = fgetc(src);
|
---|
86 | if (ch==EOF) {
|
---|
87 | break;
|
---|
88 | } else {
|
---|
89 | fputc(ch, dest);
|
---|
90 | if (ferror(dest)) {
|
---|
91 | cs_log("Error while writing to file %s (errno=%d %s)!", destfile, errno, strerror(errno));
|
---|
92 | fclose(src);
|
---|
93 | fclose(dest);
|
---|
94 | return -2;
|
---|
95 | }
|
---|
96 | }
|
---|
97 | }
|
---|
98 | fclose(src);
|
---|
99 | fclose(dest);
|
---|
100 | return(0);
|
---|
101 | }
|
---|
102 |
|
---|
103 | /* Overwrites destfile with temp_file. If forceBakOverWrite = 0, the bakfile will not be overwritten if it exists, else it will be.*/
|
---|
104 | int32_t safe_overwrite_with_bak(char *destfile, char *temp_file, char *bakfile, int32_t forceBakOverWrite) {
|
---|
105 | int32_t rc;
|
---|
106 | if (file_exists(destfile)) {
|
---|
107 | if (forceBakOverWrite != 0 || !file_exists(bakfile)) {
|
---|
108 | if (file_copy(destfile, bakfile) < 0){
|
---|
109 | cs_log("Error copying original config file %s to %s. The original config will be left untouched!", destfile, bakfile);
|
---|
110 | if (remove(temp_file) < 0)
|
---|
111 | cs_log("Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno));
|
---|
112 | return 1;
|
---|
113 | }
|
---|
114 | }
|
---|
115 | }
|
---|
116 | rc = file_copy(temp_file, destfile);
|
---|
117 | if (rc < 0) {
|
---|
118 | cs_log("An error occured while writing the new config file %s.", destfile);
|
---|
119 | if(rc == -2)
|
---|
120 | cs_log("The config will be missing or only partly filled upon next startup as this is a non-recoverable error! Please restore from backup or try again.");
|
---|
121 | if (remove(temp_file) < 0)
|
---|
122 | cs_log("Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno));
|
---|
123 | return 1;
|
---|
124 | }
|
---|
125 | if (remove(temp_file) < 0)
|
---|
126 | cs_log("Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno));
|
---|
127 | return 0;
|
---|
128 | }
|
---|