#define MODULE_LOG_PREFIX "files" #include "globals.h" #include "oscam-files.h" #include "oscam-lock.h" #include "oscam-string.h" extern CS_MUTEX_LOCK readdir_lock; extern char cs_tmpdir[200]; /* Gets the tmp dir */ char *get_tmp_dir(void) { if(cs_tmpdir[0]) { return cs_tmpdir; } #if defined(__CYGWIN__) char *d = getenv("TMPDIR"); if(!d || !d[0]) { d = getenv("TMP"); } if(!d || !d[0]) { d = getenv("TEMP"); } if(!d || !d[0]) { getcwd(cs_tmpdir, sizeof(cs_tmpdir) - 1); } cs_strncpy(cs_tmpdir, d, sizeof(cs_tmpdir)); char *p = cs_tmpdir; while(*p) { p++; } p--; if(*p != '/' && *p != '\\') { cs_strncat(cs_tmpdir, "/", sizeof(cs_tmpdir)); } cs_strncat(cs_tmpdir, "_oscam", sizeof(cs_tmpdir)); #else cs_strncpy(cs_tmpdir, "/tmp/.oscam", sizeof(cs_tmpdir)); #endif mkdir(cs_tmpdir, S_IRWXU); return cs_tmpdir; } char *get_tmp_dir_filename(char *dest, size_t destlen, const char *filename) { char *tmp_dir = get_tmp_dir(); const char *slash = "/"; if(tmp_dir[cs_strlen(tmp_dir) - 1] == '/') { slash = ""; } snprintf(dest, destlen, "%s%s%s", tmp_dir, slash, filename); return dest; } /* Return 1 if the file exists, else 0 */ bool file_exists(const char *filename) { return access(filename, R_OK) == 0; } /* Finds a file in the system PATH. Returns a newly allocated string with the full path, or NULL if not found. Caller must free() the returned string. */ char *find_in_path(const char *filename) { // If filename already has '/', don't search PATH if (strchr(filename, '/')) { return strdup(filename); } char *paths; const char *path = getenv("PATH"); if (!path || !(paths = strdup(path))) return NULL; char *saveptr = NULL; char *dir = strtok_r(paths, ":", &saveptr); char fullpath[PATH_MAX]; char *result = NULL; while (dir) { if (*dir == '\0') dir = "."; snprintf(fullpath, sizeof(fullpath), "%s/%s", dir, filename); if (file_exists(fullpath)) { result = strdup(fullpath); break; } dir = strtok_r(NULL, ":", &saveptr); } free(paths); return result; } /* Copies a file from srcfile to destfile. If an error occured before writing, -1 is returned, else -2. On success, 0 is returned.*/ int32_t file_copy(char *srcfile, char *destfile) { FILE *src, *dest; int32_t ch; src = fopen(srcfile, "r"); if(!src) { cs_log("Error opening file %s for reading (errno=%d %s)!", srcfile, errno, strerror(errno)); return -1; } dest = fopen(destfile, "w"); if(!dest) { cs_log("Error opening file %s for writing (errno=%d %s)!", destfile, errno, strerror(errno)); fclose(src); return -1; } while(1) { ch = fgetc(src); if(ch == EOF) { break; } else { fputc(ch, dest); if(ferror(dest)) { cs_log("Error while writing to file %s (errno=%d %s)!", destfile, errno, strerror(errno)); fclose(src); fclose(dest); return -2; } } } fclose(src); if(fsync(fileno(dest)) == -1) // Dodano fsync, aby wymusić zapis na dysk { cs_log("ERROR: file_copy - fsync failed for %s (errno=%d %s)!", destfile, errno, strerror(errno)); } fclose(dest); return (0); } /* Overwrites destfile with temp_file. If forceBakOverWrite = 0, the bakfile will not be overwritten if it exists, else it will be.*/ int32_t safe_overwrite_with_bak(char *destfile, char *temp_file, char *bakfile, int32_t forceBakOverWrite) { int32_t rc; if(file_exists(destfile)) { if(forceBakOverWrite != 0 || !file_exists(bakfile)) { if(file_copy(destfile, bakfile) < 0) { cs_log("ERROR: safe_overwrite_with_bak - Error copying original config file %s to %s. The original config will be left untouched!", destfile, bakfile); if(unlink(temp_file) < 0) { cs_log("ERROR: safe_overwrite_with_bak - Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno)); } return 1; } } } rc = file_copy(temp_file, destfile); if(rc < 0) { cs_log("ERROR: safe_overwrite_with_bak - An error occured while writing the new config file %s. Return code: %d, errno: %d (%s).", destfile, rc, errno, strerror(errno)); if(rc == -2) { cs_log("ERROR: safe_overwrite_with_bak - 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."); } if(unlink(temp_file) < 0) { cs_log("ERROR: safe_overwrite_with_bak - Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno)); } return 1; } if(unlink(temp_file) < 0) { cs_log("ERROR: safe_overwrite_with_bak - Error removing temp config file %s (errno=%d %s)!", temp_file, errno, strerror(errno)); } return 0; } #ifdef MODULE_GBOX char *get_gbox_filename(char *dest, size_t destlen, const char *filename) { char *tmp_dir = get_tmp_dir(); const char *slash = "/"; if(cfg.gbox_tmp_dir != NULL) { if(cfg.gbox_tmp_dir[cs_strlen(cfg.gbox_tmp_dir) - 1] == '/') { slash = ""; } snprintf(dest, destlen, "%s%s%s", cfg.gbox_tmp_dir, slash, filename); } else { if(tmp_dir[cs_strlen(tmp_dir) - 1] == '/') { slash = ""; } snprintf(dest, destlen, "%s%s%s", tmp_dir, slash, filename); } return dest; } #endif