#ifdef HAVE_CONFIG_H # include "SctConfig.h" #endif #include "SctCommon.h" #include #include #include #include #include #include #include #include uid_t procrealuid = 0; uid_t proceffuid = 0; int str_to_u(const char* s, unsigned* u){ char* p; unsigned o; errno = 0; o = strtoul(s, &p, 0); if(errno || *p){ return -1; } *u = o; return 0; } int read_complete(int fd, void* buf, size_t count){ /* 一定要讀到 count 位元組的資料才會回傳,所以只要回傳 < count * 就表示已經讀到 EOF 了 */ char* bufp = (char*)buf; size_t curcount = 0; int rval; do{ rval = read(fd, bufp, count - curcount); if(rval < 0){ return rval; }else if(rval == 0){ return curcount; }else{ bufp += rval; curcount += rval; } }while(curcount < count); return count; } int strerror_threadsafe(int errnum, char* buf, size_t buflen){ static pthread_mutex_t strerror_call_mutex = PTHREAD_MUTEX_INITIALIZER; char* rval; int rlen; pthread_mutex_lock(&strerror_call_mutex); rval = strerror(errnum); rlen = strlen(rval); if(buflen < rlen){ pthread_mutex_unlock(&strerror_call_mutex ); return -1; } strcpy(buf, rval); pthread_mutex_unlock(&strerror_call_mutex); return 0; } int sprintf_malloc(char** strstore, const char* format, ...){ int len; char* newstr; va_list ap; va_start(ap, format); len = vsnprintf(NULL, 0, format, ap) + 1; va_end(ap); newstr = malloc(len); if(newstr == NULL){ return -1; } va_start(ap, format); len = vsnprintf(newstr, len, format, ap); va_end(ap); *strstore = newstr; return len; } void checktimespec(struct timespec* arg){ long tominus; if(arg->tv_nsec >= 1000000000){ arg->tv_sec += (arg->tv_nsec / 1000000000); arg->tv_nsec %= 1000000000; }else if(arg->tv_nsec < 0){ if((-(arg->tv_nsec)) % 1000000000 == 0){ arg->tv_sec -= ((-(arg->tv_nsec)) / 1000000000); arg->tv_nsec = 0; }else{ tominus = (((-(arg->tv_nsec)) / 1000000000) + 1); arg->tv_sec -= tominus; arg->tv_nsec += tominus * 1000000000; } } } void difftimespec(start, end, out) const struct timespec* start; const struct timespec* end; struct timespec* out; { out->tv_sec = end->tv_sec - start->tv_sec; out->tv_nsec = end->tv_nsec - start->tv_nsec; if(out->tv_nsec < 0){ out->tv_nsec += 1000000000; out->tv_sec--; } } int comparetimespec(t1, t2) const struct timespec* t1; const struct timespec* t2; { if(t1->tv_sec < t2->tv_sec){ return -1; }else if(t1->tv_sec > t2->tv_sec){ return 1; }else{ if(t1->tv_nsec < t2->tv_nsec){ return -1; }else if(t1->tv_nsec > t2->tv_nsec){ return 1; }else{ return 0; } } return 0; } void save_uids(void){ /* 這個一定要先執行,不然預設 uid 就是 0 */ procrealuid = getuid(); proceffuid = geteuid(); } #ifndef HAVE_CONF_CAP void disable_setuid(void){ #ifdef _POSIX_SAVED_IDS seteuid(procrealuid); #else setreuid(proceffuid, procrealuid); #endif } void enable_setuid(void){ #ifdef _POSIX_SAVED_IDS seteuid(proceffuid); #else setreuid(procrealuid, proceffuid); #endif } #endif