📄 tools.c
字号:
/* * tools.c: Various tools * * See the main source file 'vdr.c' for copyright information and * how to reach the author. * * $Id: tools.c 1.82 2004/11/21 14:36:34 kls Exp $ */#include "tools.h"#include <ctype.h>#include <dirent.h>#include <errno.h>#include <stdlib.h>#include <sys/types.h>#include <sys/timeb.h>//#include <sys/vfs.h>#include <time.h>#include <unistd.h>//#include "i18n.h"int SysLogLevel = 3;void syslog (int log_t,...){ //Do nothing porting is too bad.}template<class T> T min ( T a , T b ) { return a <= b ? a : b; }template<class T> inline T max(T a, T b) { return a >= b ? a : b; }template<class T> inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; }template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; }int BCD2INT(int x){ return ((1000000 * BCDCHARTOINT((x >> 24) & 0xFF)) + (10000 * BCDCHARTOINT((x >> 16) & 0xFF)) + (100 * BCDCHARTOINT((x >> 8) & 0xFF)) + BCDCHARTOINT( x & 0xFF));}/*ssize_t safe_read(int filedes, void *buffer, size_t size){ for (;;) { ssize_t p = read(filedes, buffer, size); if (p < 0 && errno == EINTR) { dsyslog("EINTR while reading from file handle %d - retrying", filedes); continue; } return p; }}ssize_t safe_write(int filedes, const void *buffer, size_t size){ ssize_t p = 0; ssize_t written = size; const unsigned char *ptr = (const unsigned char *)buffer; while (size > 0) { p = write(filedes, ptr, size); if (p < 0) { if (errno == EINTR) { dsyslog("EINTR while writing to file handle %d - retrying", filedes); continue; } break; } ptr += p; size -= p; } return p < 0 ? p : written;}void writechar(int filedes, char c){ safe_write(filedes, &c, sizeof(c));}*/char *readline(FILE *f){ static char buffer[MAXPARSEBUFFER]; if (fgets(buffer, sizeof(buffer), f) > 0) { int l = strlen(buffer) - 1; if (l >= 0 && buffer[l] == '\n') buffer[l] = 0; return buffer; } return NULL;}char *strcpyrealloc(char *dest, const char *src){ if (src) { int l = max(dest ? strlen(dest) : 0, strlen(src)) + 1; // don't let the block get smaller! dest = (char *)realloc(dest, l); if (dest) strcpy(dest, src); else printf("ERROR: out of memory\n"); } else { free(dest); dest = NULL; } return dest;}char *strn0cpy(char *dest, const char *src, size_t n){ char *s = dest; for ( ; --n && (*dest = *src) != 0; dest++, src++) ; *dest = 0; return s;}char *strreplace(char *s, char c1, char c2){ char *p = s; while (p && *p) { if (*p == c1) *p = c2; p++; } return s;}char *strreplace(char *s, const char *s1, const char *s2){ char *p = strstr(s, s1); if (p) { int of = p - s; int l = strlen(s); int l1 = strlen(s1); int l2 = strlen(s2); if (l2 > l1) s = (char *)realloc(s, strlen(s) + l2 - l1 + 1); if (l2 != l1) memmove(s + of + l2, s + of + l1, l - of - l1 + 1); strncpy(s + of, s2, l2); } return s;}char *skipspace(const char *s){ while (*s && isspace(*s)) s++; return (char *)s;}char *stripspace(char *s){ if (s && *s) { for (char *p = s + strlen(s) - 1; p >= s; p--) { if (!isspace(*p)) break; *p = 0; } } return s;}char *compactspace(char *s){ if (s && *s) { char *t = stripspace(skipspace(s)); char *p = t; while (p && *p) { char *q = skipspace(p); if (q - p > 1) memmove(p + 1, q, strlen(q) + 1); p++; } if (t != s) memmove(s, t, strlen(t) + 1); } return s;}const char *strescape(const char *s, const char *chars){ static char *buffer = NULL; const char *p = s; char *t = NULL; while (*p) { if (strchr(chars, *p)) { if (!t) { buffer = (char *)realloc(buffer, 2 * strlen(s) + 1); t = buffer + (p - s); s = strcpy(buffer, s); } *t++ = '\\'; } if (t) *t++ = *p; p++; } if (t) *t = 0; return s;}bool startswith(const char *s, const char *p){ while (*p) { if (*p++ != *s++) return false; } return true;}bool endswith(const char *s, const char *p){ const char *se = s + strlen(s) - 1; const char *pe = p + strlen(p) - 1; while (pe >= p) { if (*pe-- != *se-- || (se < s && pe >= p)) return false; } return true;}bool isempty(const char *s){ return !(s && *skipspace(s));}int numdigits(int n){ char buf[16]; snprintf(buf, sizeof(buf), "%d", n); return strlen(buf);}#include <windows.h>int time_ms(void){ static time_t t0 = 0; #ifdef X11 struct timeval t; if (gettimeofday(&t, NULL) == 0) { if (t0 == 0) t0 = t.tv_sec; // this avoids an overflow (we only work with deltas) return (t.tv_sec - t0) * 1000 + t.tv_usec / 1000; } #else SYSTEMTIME t; GetSystemTime(&t); if(t0==0) t0 = t.wSecond; return (t.wSecond - t0) * 1000 + t.wMilliseconds / 1000; #endif return 0;}/*void delay_ms(int ms){ int t0 = time_ms(); while (time_ms() - t0 < ms) ;}*/bool isnumber(const char *s){ if (!*s) return false; while (*s) { if (!isdigit(*s)) return false; s++; } return true;}const char *itoa(int n){ static char buf[16]; snprintf(buf, sizeof(buf), "%d", n); return buf;}const char *AddDirectory(const char *DirName, const char *FileName){ static char *buf = NULL; free(buf); buf=new char[256]; sprintf(buf, "%s\\%s", DirName && *DirName ? DirName : ".", FileName); return buf;}/*int FreeDiskSpaceMB(const char *Directory, int *UsedMB){ if (UsedMB) *UsedMB = 0; int Free = 0; struct statfs statFs; if (statfs(Directory, &statFs) == 0) { double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize; if (UsedMB) *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg); Free = int(statFs.f_bavail / blocksPerMeg); } else LOG_ERROR_STR(Directory); return Free;}bool DirectoryOk(const char *DirName, bool LogErrors){ struct stat ds; if (stat(DirName, &ds) == 0) { if (S_ISDIR(ds.st_mode)) { if (access(DirName, R_OK | W_OK | X_OK) == 0) return true; else if (LogErrors) esyslog("ERROR: can't access %s", DirName); } else if (LogErrors) esyslog("ERROR: %s is not a directory", DirName); } else if (LogErrors) LOG_ERROR_STR(DirName); return false;}bool MakeDirs(const char *FileName, bool IsDirectory){ bool result = true; char *s = strdup(FileName); char *p = s; if (*p == '/') p++; while ((p = strchr(p, '/')) != NULL || IsDirectory) { if (p) *p = 0; struct stat fs; if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) { dsyslog("creating directory %s", s); if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { LOG_ERROR_STR(s); result = false; break; } } if (p) *p++ = '/'; else break; } free(s); return result;}bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks){ struct stat st; if (stat(FileName, &st) == 0) { if (S_ISDIR(st.st_mode)) { DIR *d = opendir(FileName); if (d) { struct dirent *e; while ((e = readdir(d)) != NULL) { if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { char *buffer; asprintf(&buffer, "%s/%s", FileName, e->d_name); if (FollowSymlinks) { int size = strlen(buffer) * 2; // should be large enough char *l = MALLOC(char, size); int n = readlink(buffer, l, size); if (n < 0) { if (errno != EINVAL) LOG_ERROR_STR(buffer); } else if (n < size) { l[n] = 0; dsyslog("removing %s", l); if (remove(l) < 0) LOG_ERROR_STR(l); } else esyslog("ERROR: symlink name length (%d) exceeded anticipated buffer size (%d)", n, size); free(l); } dsyslog("removing %s", buffer); if (remove(buffer) < 0) LOG_ERROR_STR(buffer); free(buffer); } } closedir(d); } else { LOG_ERROR_STR(FileName); return false; } } dsyslog("removing %s", FileName); if (remove(FileName) < 0) { LOG_ERROR_STR(FileName); return false; } } else if (errno != ENOENT) { LOG_ERROR_STR(FileName); return false; } return true;}bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis){ DIR *d = opendir(DirName); if (d) { bool empty = true; struct dirent *e; while ((e = readdir(d)) != NULL) { if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) { char *buffer; asprintf(&buffer, "%s/%s", DirName, e->d_name); struct stat st; if (stat(buffer, &st) == 0) { if (S_ISDIR(st.st_mode)) { if (!RemoveEmptyDirectories(buffer, true)) empty = false; } else empty = false; } else { LOG_ERROR_STR(buffer); free(buffer); return false; } free(buffer); } } closedir(d); if (RemoveThis && empty) { dsyslog("removing %s", DirName); if (remove(DirName) < 0) { LOG_ERROR_STR(DirName); return false; } } return empty; } else LOG_ERROR_STR(DirName); return false;}char *ReadLink(const char *FileName){ char RealName[PATH_MAX]; const char *TargetName = NULL; int n = readlink(FileName, RealName, sizeof(RealName) - 1); if (n < 0) { if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink TargetName = FileName; else // some other error occurred LOG_ERROR_STR(FileName); } else if (n < int(sizeof(RealName))) { // got it! RealName[n] = 0; TargetName = RealName; } else esyslog("ERROR: symlink's target name too long: %s", FileName); return TargetName ? strdup(TargetName) : NULL;}bool SpinUpDisk(const char *FileName){ static char *buf = NULL; for (int n = 0; n < 10; n++) { free(buf); if (DirectoryOk(FileName)) asprintf(&buf, "%s/vdr-%06d", *FileName ? FileName : ".", n); else asprintf(&buf, "%s.vdr-%06d", FileName, n); if (access(buf, F_OK) != 0) { // the file does not exist timeval tp1, tp2; gettimeofday(&tp1, NULL); int f = open(buf, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // O_SYNC doesn't work on all file systems if (f >= 0) { close(f); system("sync"); remove(buf); gettimeofday(&tp2, NULL); double seconds = (((long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((long long)tp1.tv_sec * 1000000 + tp1.tv_usec)) / 1000000.0; if (seconds > 0.5) dsyslog("SpinUpDisk took %.2f seconds\n", seconds);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -