📄 lib.c
字号:
/* * lib.c * Global utility functions. * * Copyright (c) 2003 Christoph Pfisterer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */#include "disktype.h"#include <stdarg.h>#define USE_BINARY_SEARCH 0#define DEBUG_SIZE 0#ifdef USE_IOCTL_LINUX#include <sys/ioctl.h>#include <linux/fs.h>#endif#ifdef USE_IOCTL_FREEBSD#include <sys/disklabel.h>#endif#ifdef USE_IOCTL_DARWIN#include <sys/ioctl.h>#include <sys/disk.h>#endif#if USE_BINARY_SEARCHint check_position(int f, U64 pos);#endifvoid dt_getfilesize(int f, SOURCE* s) { off_t result; if(s == NULL) return; /* Determine the size using various methods. The first method that works is used. */ /* * lseek() to the end: * Works on files. On some systems (Linux), this also works on devices. */ if (!s->size_known) { result = lseek(f, 0, SEEK_END);#if DEBUG_SIZE printf("Size: lseek returned %lld\n", result);#endif if (result > 0) { s->size_known = 1; s->size = result; } }#ifdef USE_IOCTL_LINUX /* * ioctl, Linux style: * Works on certain devices. */#ifdef BLKGETSIZE64#define u64 __u64 /* workaround for broken header file */ if (!s->size_known && s->type != DT_FILE) { U64 devsize; if (ioctl(f, BLKGETSIZE64, (void *)&devsize) >= 0) { s->size_known = 1; s->size = devsize;#if DEBUG_SIZE printf("Size: Linux 64-bit ioctl reports %llu\n", s->size);#endif } }#undef u64#endif if (!s->size_known && s->type != DT_FILE) { U32 blockcount; if (ioctl(f, BLKGETSIZE, (void *)&blockcount) >= 0) { s->size_known = 1; s->size = (U64)blockcount * 512;#if DEBUG_SIZE printf("Size: Linux 32-bit ioctl reports %llu (%lu blocks)\n", s->size, blockcount);#endif } }#endif#ifdef USE_IOCTL_FREEBSD /* * ioctl, FreeBSD style: * Works on partitioned hard disks or somthing like that. */ if (!s->size_known && s->type != DT_FILE) { struct disklabel dl; if (ioctl(f, DIOCGDINFO, &dl) >= 0) { s->size_known = 1; s->size = (U64) dl.d_ncylinders * dl.d_secpercyl * dl.d_secsize; /* TODO: check this, it's the whole disk size... */#if DEBUG_SIZE printf("Size: FreeBSD ioctl reports %llu\n", s->size);#endif } }#endif#ifdef USE_IOCTL_DARWIN /* * ioctl, Darwin style: * Works on certain devices. */ if (!s->size_known && s->type != DT_FILE) { U32 blocksize; U64 blockcount; if (ioctl(f, DKIOCGETBLOCKSIZE, (void *)&blocksize) >= 0) { if (ioctl(f, DKIOCGETBLOCKCOUNT, (void *)&blockcount) >= 0) { s->size_known = 1; s->size = blockcount * blocksize;#if DEBUG_SIZE printf("Size: Darwin ioctl reports %llu (%llu blocks of %lu bytes)\n", s->size, blockcount, blocksize);#endif } } }#endif#if USE_BINARY_SEARCH /* * binary search: * Works on anything that can seek, but is quite expensive. */ if (!s->size_known) { U64 lower, upper, current; /* TODO: check that the target can seek at all */#if DEBUG_SIZE printf("Size: Doing a binary search\n");#endif /* first, find an upper bound starting from a reasonable guess */ lower = 0; upper = 1024 * 1024; /* start with 1MB */ while (check_position(f, upper)) { lower = upper; upper <<= 2; } /* second, nail down the size between the lower and upper bounds */ while (upper > lower + 1) { current = (lower + upper) >> 1; if (check_position(f, current)) lower = current; else upper = current; } s->size_known = 1; s->size = lower + 1;#if DEBUG_SIZE printf("Size: Binary search reports %llu\n", s->size);#endif }#endif return;}/* * check if the given position is inside the file's size */#if USE_BINARY_SEARCHint check_position(int f, U64 pos) { char buf[2];#if DEBUG_SIZE printf(" Probing %llu\n", pos);#endif if(lseek(f, pos, SEEK_SET) != pos) return 0; if (read(f, buf, 1) != 1) return 0; return 1;}#endif/* * endian-aware data access */U16 get_be_short(void *from) { U8 *p = from; return ((U16)(p[0]) << 8) + (U16)p[1];}U32 get_be_long(void *from) { U8 *p = from; return ((U32)(p[0]) << 24) + ((U32)(p[1]) << 16) + ((U32)(p[2]) << 8) + (U32)p[3];}U64 get_be_quad(void *from) { U8 *p = from; return ((U64)(p[0]) << 56) + ((U64)(p[1]) << 48) + ((U64)(p[2]) << 40) + ((U64)(p[3]) << 32) + ((U64)(p[4]) << 24) + ((U64)(p[5]) << 16) + ((U64)(p[6]) << 8) + (U64)p[7];}U16 get_le_short(void *from) { U8 *p = from; return ((U16)(p[1]) << 8) + (U16)p[0];}U32 get_le_long(void *from) { U8 *p = from; return ((U32)(p[3]) << 24) + ((U32)(p[2]) << 16) + ((U32)(p[1]) << 8) + (U32)p[0];}U64 get_le_quad(void *from) { U8 *p = from; return ((U64)(p[7]) << 56) + ((U64)(p[6]) << 48) + ((U64)(p[5]) << 40) + ((U64)(p[4]) << 32) + ((U64)(p[3]) << 24) + ((U64)(p[2]) << 16) + ((U64)(p[1]) << 8) + (U64)p[0];}U16 get_ve_short(int endianness, void *from) { if (endianness) return get_le_short(from); else return get_be_short(from);}U32 get_ve_long(int endianness, void *from) { if (endianness) return get_le_long(from); else return get_be_long(from);}U64 get_ve_quad(int endianness, void *from) { if (endianness) return get_le_quad(from); else return get_be_quad(from);}const char * get_ve_name(int endianness) { if (endianness) return _T("little-endian"); else return _T("big-endian");}/* * more data access */void get_string(void *from, int len, char *to) { if (len > 255) len = 255; memcpy(to, from, len); to[len] = 0;}void get_pstring(void *from, char *to) { int len = *(unsigned char *)from; memcpy(to, (char *)from + 1, len); to[len] = 0;}void get_padded_string(void *from, int len, char pad, char *to) { int pos; get_string(from, len, to); for (pos = strlen(to) - 1; pos >= 0 && to[pos] == pad; pos--) to[pos] = 0;}int find_memory(void *haystack, int haystack_len, void *needle, int needle_len) { int searchlen = haystack_len - needle_len + 1; int pos = 0; void *p; while (pos < searchlen) { p = memchr((char *)haystack + pos, *(unsigned char *)needle, searchlen - pos); if (p == NULL) return -1; pos = (char *)p - (char *)haystack; if (memcmp(p, needle, needle_len) == 0) return pos; pos++; } return -1;}/* * error functions */#ifdef DEBUGvoid debugmessage(char* function, int line, const char *msg, ...) { va_list par; char buf[4096]; va_start(par, msg); vsnprintf(buf, 4096, msg, par); va_end(par); fprintf(stderr, "* DEBUG *:%s:%i: %s\n", function, line, buf);}#endifvoid error(const char *msg, ...) { va_list par; char buf[4096]; va_start(par, msg); vsnprintf(buf, 4096, msg, par); va_end(par); fprintf(stderr, "*** ERROR ***: %s\n", buf);}void errore(const char *msg, ...) { va_list par; char buf[4096]; char* error; va_start(par, msg); vsnprintf(buf, 4096, msg, par); va_end(par); error = strerror(errno); fprintf(stderr, "*** ERROR ***: %s: %s\n", buf, error);}void bailout(const char *msg, ...) { va_list par; char buf[4096]; va_start(par, msg); vsnprintf(buf, 4096, msg, par); va_end(par); fprintf(stderr, "*** FATAL ***: %s\n", buf); exit(1);}void bailoute(const char *msg, ...) { va_list par; char buf[4096]; char* error; va_start(par, msg); vsnprintf(buf, 4096, msg, par); va_end(par); error = strerror(errno); fprintf(stderr, "*** FATAL ***: %s: %s\n", buf, error); exit(1);}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -