📄 utility.cpp
字号:
else pout("%s\n",errormessage); } else if (message && *message) pout("%s\n",message); return;}// Prints a warning message for a failed regular expression compilation from// regcomp().void printregexwarning(int errcode, regex_t *compiled){ size_t length = regerror(errcode, compiled, NULL, 0); char *buffer = (char*)malloc(length); if (!buffer){ pout("Out of memory in printregexwarning()\n"); return; } regerror(errcode, compiled, buffer, length); pout("%s\n", buffer); free(buffer); return;}// POSIX extended regular expressions interpret unmatched ')' ordinary:// "The close-parenthesis shall be considered special in this context// only if matched with a preceding open-parenthesis."//// Actual '(...)' nesting errors remain undetected on strict POSIX// implementations (glibc) but an error is reported on others (Cygwin).// // The check below is rather incomplete because it does not handle// e.g. '\)' '[)]'.// But it should work for the regex subset used in drive database.static int check_regex_nesting(const char * pattern){ int level = 0, i; for (i = 0; pattern[i] && level >= 0; i++) { switch (pattern[i]) { case '(': level++; break; case ')': level--; break; } } return level;}// A wrapper for regcomp(). Returns zero for success, non-zero otherwise.int compileregex(regex_t *compiled, const char *pattern, int cflags){ int errorcode; if ( (errorcode = regcomp(compiled, pattern, cflags)) || check_regex_nesting(pattern) < 0 ) { pout("Internal error: unable to compile regular expression \"%s\" ", pattern); if (errorcode) printregexwarning(errorcode, compiled); else pout("Unmatched ')'\n"); pout("Please inform smartmontools developers at " PACKAGE_BUGREPORT "\n"); return 1; } return 0;}// Splits an argument to the -r option into a name part and an (optional) // positive integer part. s is a pointer to a string containing the// argument. After the call, s will point to the name part and *i the// integer part if there is one or 1 otherwise. Note that the string s may// be changed by this function. Returns zero if successful and non-zero// otherwise.int split_report_arg(char *s, int *i){ if ((s = strchr(s, ','))) { // Looks like there's a name part and an integer part. char *tailptr; *s++ = '\0'; if (*s == '0' || !isdigit((int)*s)) // The integer part must be positive return 1; errno = 0; *i = (int) strtol(s, &tailptr, 10); if (errno || *tailptr != '\0') return 1; } else { // There's no integer part. *i = 1; } return 0;}// same as above but sets *i to -1 if missing , argumentint split_report_arg2(char *s, int *i){ char *tailptr; s+=6; if (*s=='\0' || !isdigit((int)*s)) { // What's left must be integer *i=-1; return 1; } errno = 0; *i = (int) strtol(s, &tailptr, 10); if (errno || *tailptr != '\0') { *i=-1; return 1; } return 0;}#ifndef HAVE_STRTOULL// Replacement for missing strtoull() (Linux with libc < 6, MSVC 6.0)// Functionality reduced to split_selective_arg()'s requirements.static uint64_t strtoull(const char * p, char * * endp, int base){ uint64_t result, maxres; int i = 0; char c = p[i++]; // assume base == 0 if (c == '0') { if (p[i] == 'x' || p[i] == 'X') { base = 16; i++; } else base = 8; c = p[i++]; } else base = 10; result = 0; maxres = ~(uint64_t)0 / (unsigned)base; for (;;) { unsigned digit; if ('0' <= c && c <= '9') digit = c - '0'; else if ('A' <= c && c <= 'Z') digit = c - 'A' + 10; else if ('a' <= c && c <= 'z') digit = c - 'a' + 10; else break; if (digit >= (unsigned)base) break; if (!( result < maxres || (result == maxres && digit <= ~(uint64_t)0 % (unsigned)base))) { result = ~(uint64_t)0; errno = ERANGE; // return on overflow break; } result = result * (unsigned)base + digit; c = p[i++]; } *endp = (char *)p + i - 1; return result;}#endif // HAVE_STRTOLL// Splits an argument to the -t option that is assumed to be of the form// "selective,%lld-%lld" (prefixes of "0" (for octal) and "0x"/"0X" (for hex)// are allowed). The first long long int is assigned to *start and the second// to *stop. Returns zero if successful and non-zero otherwise.int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode){ char *tailptr; if (!(s = strchr(s, ','))) return 1; bool add = false; if (!isdigit((int)(*++s))) { *start = *stop = 0; if (!strncmp(s, "redo", 4)) *mode = SEL_REDO; else if (!strncmp(s, "next", 4)) *mode = SEL_NEXT; else if (!strncmp(s, "cont", 4)) *mode = SEL_CONT; else return 1; s += 4; if (!*s) return 0; if (*s != '+') return 1; } else { *mode = SEL_RANGE; errno = 0; // Last argument to strtoull (the base) is 0 meaning that decimal is assumed // unless prefixes of "0" (for octal) or "0x"/"0X" (for hex) are used. *start = strtoull(s, &tailptr, 0); s = tailptr; add = (*s == '+'); if (!(!errno && (add || *s == '-'))) return 1; if (!strcmp(s, "-max")) { *stop = ~(uint64_t)0; // replaced by max LBA later return 0; } } *stop = strtoull(s+1, &tailptr, 0); if (errno || *tailptr != '\0') return 1; if (add) { if (*stop > 0) (*stop)--; *stop += *start; // -t select,N+M => -t select,N,(N+M-1) } return 0;}int64_t bytes = 0;// Helps debugging. If the second argument is non-negative, then// decrement bytes by that amount. Else decrement bytes by (one plus)// length of null terminated string.void *FreeNonZero1(void *address, int size, int line, const char* file){ if (address) { if (size<0) bytes-=1+strlen((char*)address); else bytes-=size; return CheckFree1(address, line, file); } return NULL;}// To help with memory checking. Use when it is known that address is// NOT null.void *CheckFree1(void *address, int whatline, const char* file){ if (address){ free(address); return NULL; } PrintOut(LOG_CRIT, "Internal error in CheckFree() at line %d of file %s\n%s", whatline, file, reportbug); EXIT(EXIT_BADCODE);}// A custom version of calloc() that tracks memory usevoid *Calloc(size_t nmemb, size_t size) { void *ptr=calloc(nmemb, size); if (ptr) bytes+=nmemb*size; return ptr;}// A custom version of strdup() that keeps track of how much memory is// being allocated. If mustexist is set, it also throws an error if we// try to duplicate a NULL string.char *CustomStrDup(const char *ptr, int mustexist, int whatline, const char* file){ char *tmp; // report error if ptr is NULL and mustexist is set if (ptr==NULL){ if (mustexist) { PrintOut(LOG_CRIT, "Internal error in CustomStrDup() at line %d of file %s\n%s", whatline, file, reportbug); EXIT(EXIT_BADCODE); } else return NULL; } // make a copy of the string... tmp=strdup(ptr); if (!tmp) { PrintOut(LOG_CRIT, "No memory to duplicate string %s at line %d of file %s\n", ptr, whatline, file); EXIT(EXIT_NOMEM); } // and track memory usage bytes+=1+strlen(ptr); return tmp;}// Returns nonzero if region of memory contains non-zero entriesint nonempty(unsigned char *testarea,int n){ int i; for (i=0;i<n;i++) if (testarea[i]) return 1; return 0;}// This routine converts an integer number of milliseconds into a test// string of the form Xd+Yh+Zm+Ts.msec. The resulting text string is// written to the array.void MsecToText(unsigned int msec, char *txt){ int start=0; unsigned int days, hours, min, sec; days = msec/86400000U; msec -= days*86400000U; hours = msec/3600000U; msec -= hours*3600000U; min = msec/60000U; msec -= min*60000U; sec = msec/1000U; msec -= sec*1000U; if (days) { txt += sprintf(txt, "%2dd+", (int)days); start=1; } sprintf(txt, "%02d:%02d:%02d.%03d", (int)hours, (int)min, (int)sec, (int)msec); return;}#ifndef HAVE_WORKING_SNPRINTF// Some versions of (v)snprintf() don't append null char on overflow (MSVCRT.DLL),// and/or return -1 on overflow (old Linux).// Below are sane replacements substituted by #define in utility.h.#undef vsnprintf#if defined(_WIN32) && defined(_MSC_VER)#define vsnprintf _vsnprintf#endifint safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap){ int i; if (size <= 0) return 0; i = vsnprintf(buf, size, fmt, ap); if (0 <= i && i < size) return i; buf[size-1] = 0; return strlen(buf); // Note: cannot detect for overflow, not necessary here.}int safe_snprintf(char *buf, int size, const char *fmt, ...){ int i; va_list ap; va_start(ap, fmt); i = safe_vsnprintf(buf, size, fmt, ap); va_end(ap); return i;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -