📄 tools.c
字号:
return true; } else LOG_ERROR_STR(buf); } } esyslog("ERROR: SpinUpDisk failed"); return false;}time_t LastModifiedTime(const char *FileName){ struct stat fs; if (stat(FileName, &fs) == 0) return fs.st_mtime; return 0;}const char *WeekDayName(int WeekDay){ static char buffer[4]; WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with monday==0! if (0 <= WeekDay && WeekDay <= 6) { const char *day = tr("MonTueWedThuFriSatSun"); day += WeekDay * 3; strncpy(buffer, day, 3); return buffer; } else return "???";}const char *WeekDayName(time_t t){ struct tm tm_r; return WeekDayName(localtime(&t, &tm_r)->tm_wday);}const char *DayDateTime(time_t t){ static char buffer[32]; if (t == 0) time(&t); struct tm tm_r; tm *tm = localtime_r(&t, &tm_r); snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d", WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min); return buffer;}// --- cPoller ---------------------------------------------------------------cPoller::cPoller(int FileHandle, bool Out){ numFileHandles = 0; Add(FileHandle, Out);}bool cPoller::Add(int FileHandle, bool Out){ if (FileHandle >= 0) { for (int i = 0; i < numFileHandles; i++) { if (pfd[i].fd == FileHandle && pfd[i].events == (Out ? POLLOUT : POLLIN)) return true; } if (numFileHandles < MaxPollFiles) { pfd[numFileHandles].fd = FileHandle; pfd[numFileHandles].events = Out ? POLLOUT : POLLIN; pfd[numFileHandles].revents = 0; numFileHandles++; return true; } esyslog("ERROR: too many file handles in cPoller"); } return false;}bool cPoller::Poll(int TimeoutMs){ if (numFileHandles) { if (poll(pfd, numFileHandles, TimeoutMs) != 0) return true; // returns true even in case of an error, to let the caller // access the file and thus see the error code } return false;}// --- cFile -----------------------------------------------------------------#define FD_SETSIZE 20bool cFile::files[FD_SETSIZE] = { false };int cFile::maxFiles = 0;cFile::cFile(void){ f = -1;}cFile::~cFile(){ Close();}bool cFile::Open(const char *FileName, int Flags, mode_t Mode){ if (!IsOpen()) return Open(open(FileName, Flags, Mode)); esyslog("ERROR: attempt to re-open %s", FileName); return false;}bool cFile::Open(int FileDes){ if (FileDes >= 0) { if (!IsOpen()) { f = FileDes; if (f >= 0) { if (f < FD_SETSIZE) { if (f >= maxFiles) maxFiles = f + 1; if (!files[f]) files[f] = true; else esyslog("ERROR: file descriptor %d already in files[]", f); return true; } else esyslog("ERROR: file descriptor %d is larger than FD_SETSIZE (%d)", f, FD_SETSIZE); } } else esyslog("ERROR: attempt to re-open file descriptor %d", FileDes); } return false;}void cFile::Close(void){ if (f >= 0) { close(f); files[f] = false; f = -1; }}bool cFile::Ready(bool Wait){ return f >= 0 && AnyFileReady(f, Wait ? 1000 : 0);}bool cFile::AnyFileReady(int FileDes, int TimeoutMs){ fd_set set; FD_ZERO(&set); for (int i = 0; i < maxFiles; i++) { if (files[i]) FD_SET(i, &set); } if (0 <= FileDes && FileDes < FD_SETSIZE && !files[FileDes]) FD_SET(FileDes, &set); // in case we come in with an arbitrary descriptor if (TimeoutMs == 0) TimeoutMs = 10; // load gets too heavy with 0 struct timeval timeout; timeout.tv_sec = TimeoutMs / 1000; timeout.tv_usec = (TimeoutMs % 1000) * 1000; return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && (FileDes < 0 || FD_ISSET(FileDes, &set));}bool cFile::FileReady(int FileDes, int TimeoutMs){ fd_set set; struct timeval timeout; FD_ZERO(&set); FD_SET(FileDes, &set); if (TimeoutMs >= 0) { if (TimeoutMs < 100) TimeoutMs = 100; timeout.tv_sec = TimeoutMs / 1000; timeout.tv_usec = (TimeoutMs % 1000) * 1000; } return select(FD_SETSIZE, &set, NULL, NULL, (TimeoutMs >= 0) ? &timeout : NULL) > 0 && FD_ISSET(FileDes, &set);}bool cFile::FileReadyForWriting(int FileDes, int TimeoutMs){ fd_set set; struct timeval timeout; FD_ZERO(&set); FD_SET(FileDes, &set); if (TimeoutMs < 100) TimeoutMs = 100; timeout.tv_sec = 0; timeout.tv_usec = TimeoutMs * 1000; return select(FD_SETSIZE, NULL, &set, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set);}// --- cSafeFile -------------------------------------------------------------cSafeFile::cSafeFile(const char *FileName){ f = NULL; //fileName = ReadLink(FileName); strcpy(fileName,FileName); tempName = fileName ? MALLOC(char, strlen(fileName) + 5) : NULL; if (tempName) strcat(strcpy(tempName, fileName), ".$$$");}cSafeFile::~cSafeFile(){ if (f) fclose(f);// unlink(tempName); free(fileName); free(tempName);}bool cSafeFile::Open(void){ if (!f && fileName && tempName) { f = fopen(tempName, "w"); if (!f) LOG_ERROR_STR(tempName); } return f != NULL;}bool cSafeFile::Close(void){ bool result = true; if (f) { if (ferror(f) != 0) { LOG_ERROR_STR(tempName); result = false; } if (fclose(f) < 0) { LOG_ERROR_STR(tempName); result = false; } f = NULL; if (result && rename(tempName, fileName) < 0) { LOG_ERROR_STR(fileName); result = false; } } else result = false; return result;}*/// --- cLockFile -------------------------------------------------------------/*#define LOCKFILENAME ".lock-vdr"#define LOCKFILESTALETIME 600 // seconds before considering a lock file "stale"cLockFile::cLockFile(const char *Directory){ fileName = NULL; f = -1; if (DirectoryOk(Directory)) asprintf(&fileName, "%s/%s", Directory, LOCKFILENAME);}cLockFile::~cLockFile(){ Unlock(); free(fileName);}bool cLockFile::Lock(int WaitSeconds){ if (f < 0 && fileName) { time_t Timeout = time(NULL) + WaitSeconds; do { f = open(fileName, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (f < 0) { if (errno == EEXIST) { struct stat fs; if (stat(fileName, &fs) == 0) { if (abs(time(NULL) - fs.st_mtime) > LOCKFILESTALETIME) { esyslog("ERROR: removing stale lock file '%s'", fileName); if (remove(fileName) < 0) { LOG_ERROR_STR(fileName); break; } continue; } } else if (errno != ENOENT) { LOG_ERROR_STR(fileName); break; } } else { LOG_ERROR_STR(fileName); break; } if (WaitSeconds) sleep(1); } } while (f < 0 && time(NULL) < Timeout); } return f >= 0;}void cLockFile::Unlock(void){ if (f >= 0) { close(f); remove(fileName); f = -1; }}*/// --- cListObject -----------------------------------------------------------cListObject::cListObject(void){ prev = next = NULL;}cListObject::~cListObject(){}void cListObject::Append(cListObject *Object){ next = Object; Object->prev = this;}void cListObject::Insert(cListObject *Object){ prev = Object; Object->next = this;}void cListObject::Unlink(void){ if (next) next->prev = prev; if (prev) prev->next = next; next = prev = NULL;}int cListObject::Index(void){ cListObject *p = prev; int i = 0; while (p) { i++; p = p->prev; } return i;}// --- cListBase -------------------------------------------------------------cListBase::cListBase(void){ objects = lastObject = NULL;}cListBase::~cListBase(){ Clear();}void cListBase::Add(cListObject *Object, cListObject *After){ if (After && After != lastObject) { After->Next()->Insert(Object); After->Append(Object); } else { if (lastObject) lastObject->Append(Object); else objects = Object; lastObject = Object; }}void cListBase::Ins(cListObject *Object, cListObject *Before){ if (Before && Before != objects) { Before->Prev()->Append(Object); Before->Insert(Object); } else { if (objects) objects->Insert(Object); else lastObject = Object; objects = Object; }}void cListBase::Del(cListObject *Object, bool DeleteObject){ if (Object == objects) objects = Object->Next(); if (Object == lastObject) lastObject = Object->Prev(); Object->Unlink(); if (DeleteObject) delete Object;}void cListBase::Move(int From, int To){ Move(Get(From), Get(To));}void cListBase::Move(cListObject *From, cListObject *To){ if (From && To) { if (From->Index() < To->Index()) To = To->Next(); if (From == objects) objects = From->Next(); if (From == lastObject) lastObject = From->Prev(); From->Unlink(); if (To) { if (To->Prev()) To->Prev()->Append(From); From->Append(To); } else { lastObject->Append(From); lastObject = From; } if (!From->Prev()) objects = From; }}void cListBase::Clear(void){ while (objects) { cListObject *object = objects->Next(); delete objects; objects = object; } objects = lastObject = NULL;}cListObject *cListBase::Get(int Index) const{ if (Index < 0) return NULL; cListObject *object = objects; while (object && Index-- > 0) object = object->Next(); return object;}int cListBase::Count(void) const{ int n = 0; cListObject *object = objects; while (object) { n++; object = object->Next(); } return n;}static int CompareListObjects(const void *a, const void *b){ const cListObject *la = *(const cListObject **)a; const cListObject *lb = *(const cListObject **)b; return la->Compare(*lb);}void cListBase::Sort(void){ int n = Count(); cListObject *a[n]; cListObject *object = objects; int i = 0; while (object && i < n) { a[i++] = object; object = object->Next(); } qsort(a, n, sizeof(cListObject *), CompareListObjects); objects = lastObject = NULL; for (i = 0; i < n; i++) { a[i]->Unlink(); Add(a[i]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -