Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
/*
* exifrescue -- salvage EXIF and/or JFIF files from disk image
* ディスクイメージファイル、あるいはローデバイスを読んで
* JPEGファイルをサルベージする
*
* ※ wipe-out で全消去したデバイスやイメージからは
* ※ 逆立ちしてもJPEGファイルをサルベージできません
*
* revision history
* 0.0: Sep. 22, 2011 by Dai ISHIJIMA
* 0.1: Aug. 9, 2013 (offset, strtol)
*
* example:
* % exifrescue disk.img
* % exifrescue -v -l 4m -m 8g /dev/da0s1
*/
#include
#include
#include
#include
#ifdef NO_OFF_T_FSEEKO
#define off_t long
#define fseeko fseek
#define ftello ftell
#endif
#define YES 1
#define NO 0
char *prog;
#define shift --argc; ++argv
#define MAXBUF 65536
#define MAXPATH 4096
#define BLKSIZ (1 * 1024)
#define MINLEN (64 * 1024)
#define MAXLEN (2 * 1024 * 1024)
#define OFSLEN 0
#define IMGSIZ ((long long int)8 * 1024 * 1024 * 1024)
#define IS_EXIF 'e'
#define IS_JFIF 'j'
#define SOI 0xffd8
#define FORMOFS 6
#define FORMLEN 4
#define EXIF "Exif"
#define JFIF "JFIF"
#define hi(x) (((x) >> 8) & 0xff)
#define lo(x) ((x) & 0xff)
#define hilo(x,y) (((x) << 8) + (y))
/* JPEGの先頭マーカー (SOI) か? */
int is_soi(unsigned char *buf)
{
if (hilo(buf[0], buf[1]) == SOI) {
return(YES);
}
return(NO);
}
/* JPEGファイルの先頭か */
int isheader(unsigned char *buf, int len, int chkeof)
{
int n;
if (buf == NULL) {
return(-1);
}
if (is_soi(buf)) {
if (strncasecmp(EXIF, (char *)(&buf[FORMOFS]), FORMLEN) == 0) {
return(IS_EXIF);
}
if (strncasecmp(JFIF, (char *)(&buf[FORMOFS]), FORMLEN) == 0) {
return(IS_JFIF);
}
}
if (chkeof) { /* 00 か ff が連続していたらJPEGの終了と判断 */
for (n = 1; n < len; n++) {
if (buf[n] != buf[0]) {
return(0);
}
}
if ((buf[0] == 0) || (buf[0] == 0xff)) {
return(-1);
}
}
return(0);
}
/* イメージファイルを先頭からスキャンしてJPEG画像を復元 */
void salvage(FILE *fp, int blksiz, int minlen, int maxlen, int ofslen,
off_t imgsiz, int chkeof, char *path, int verbose)
{
off_t pos;
off_t nextpos, startpos;
int len;
FILE *ofp;
unsigned char buf[MAXBUF];
int type;
char filnam[MAXPATH];
int n;
n = 0;
if (imgsiz <= 0) {
if (fseeko(fp, 0, SEEK_END) < 0) {
fprintf(stderr, "%s: not a seekable stream\n", prog);
exit(1);
}
imgsiz = ftello(fp);
}
if (verbose > 0) {
fprintf(stderr, "%s: imgsiz: %lld\n", prog, (long long int)imgsiz);
}
if (imgsiz <= 0) {
fprintf(stderr, "%s: imgsiz: %lld, assumed %lld\n",
prog, (long long int)imgsiz, IMGSIZ);
imgsiz = IMGSIZ;
}
fseeko(fp, ofslen, SEEK_SET);
nextpos = startpos = pos = ftello(fp);
if (pos < 0) { /* fseek/fseekoできないときは負のはず */
fprintf(stderr, "%s: not a seekable stream\n", prog);
exit(1);
}
if (verbose > 0) {
fprintf(stderr, "%s: start at %08lx\n", prog, (unsigned long)pos);
}
len = fread(buf, 1, blksiz, fp);
ofp = NULL;
while (len > 0) {
type = isheader(buf, len, chkeof);
if ((type == IS_EXIF) || (type == IS_JFIF)) { /* JPEGファイル発見 */
if (verbose > 0) {
fprintf(stderr, "%s: JPEG found, type %c, at %08lx (%d%%)\n",
prog, type, (unsigned long)pos,
(unsigned int)(100 * pos / imgsiz));
}
if (ofp == NULL) { /* ファイルに出力 */
nextpos = startpos = pos;
sprintf(filnam, "%s%c%07lx.jpg", path, type,
(unsigned long)(pos / BLKSIZ));
if (verbose > 0) {
fprintf(stderr, "%s: open %s\n", prog, filnam);
}
if ((ofp = fopen(filnam, "w")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", prog, filnam);
exit(1);
}
}
else { /* ファイル出力中なら次の開始位置を記憶 */
if (pos - startpos < minlen) {
if (nextpos <= startpos) {
nextpos = pos;
if (verbose > 1) {
fprintf(stderr, "%s: set next pos: %08lx\n",
prog, (unsigned long)nextpos);
}
}
}
else { /* ある程度の長さを出力していたら閉じる */
if (verbose > 1) {
fprintf(stderr, "%s: file closed at %08lx\n",
prog, (unsigned long)pos);
}
fclose(ofp);
++n;
ofp = NULL;
if (nextpos <= startpos) {
nextpos = pos;
}
fseeko(fp, nextpos, SEEK_SET);
}
}
}
if (ofp != NULL) { /* ファイル出力中 */
if (type >= 0) {
fwrite(buf, 1, len, ofp);
}
if ((pos - startpos > maxlen) || (type < 0)) {
/* ファイルの終端に達したと判断したら閉じる */
if (verbose > 1) {
if (type < 0) {
fprintf(stderr, "%s: detect EOF\n", prog);
}
fprintf(stderr, "%s: file closed at %08lx\n",
prog, (unsigned long)pos);
}
fclose(ofp);
++n;
ofp = NULL;
if (nextpos > startpos) {
fseeko(fp, nextpos, SEEK_SET);
}
}
}
if ((pos = ftello(fp)) < 0) {
fprintf(stderr, "%s: not a seekable stream\n", prog);
exit(1);
}
len = fread(buf, 1, blksiz, fp);
}
if (ofp != NULL) {
fclose(ofp);
++n;
}
if (verbose > 1) {
fprintf(stderr, "%s: wrote %d file(s)\n", prog, n);
}
}
void usage()
{
fprintf(stderr, "Usage: %s [option] [disk image]\n", prog);
fprintf(stderr, " options:\n");
fprintf(stderr, "\t-b # set block size [%d]\n", BLKSIZ);
fprintf(stderr, "\t-s # set minimum length [%d]\n", MINLEN);
fprintf(stderr, "\t-l # set maximum length [%d]\n", MAXLEN);
fprintf(stderr, "\t-m # set disk image length (auto detect)\n");
fprintf(stderr, "\t-o # set offset length [%d]\n", OFSLEN);
fprintf(stderr, "\t-x # same as -o, but uses strtol()\n");
fprintf(stderr, "\t-e detect end of file\n");
fprintf(stderr, "\t-p path set output path [current directory]\n");
fprintf(stderr, "\t-v be verbose\n");
}
/* k や m がついていたら、kバイト、Mバイトと解釈 */
long long int bytesize(char *s)
{
long long int n;
n = atoi(s);
if (s[strlen(s) - 1] == 'k') {
n *= 1024;
}
if (s[strlen(s) - 1] == 'm') {
n *= (1024 * 1024);
}
if (s[strlen(s) - 1] == 'g') {
n *= (1024 * 1024 * 1024);
}
return(n);
}
int main(int argc, char *argv[])
{
int blksiz, minlen, maxlen, ofslen;
char path[MAXPATH];
FILE *fp;
int chkeof;
int verbose;
off_t imgsiz;
prog = *argv;
shift;
blksiz = minlen = maxlen = 0;
ofslen = -1;
verbose = 0;
chkeof = NO;
strcpy(path, "");
while ((argc > 0) && (argv[0][0] == '-')) {
if (argv[0][1] == 'b') {
shift;
blksiz = bytesize(*argv);
}
else if (argv[0][1] == 's') {
shift;
minlen = bytesize(*argv);
}
else if (argv[0][1] == 'l') {
shift;
maxlen = bytesize(*argv);
}
else if (argv[0][1] == 'm') {
shift;
imgsiz = bytesize(*argv);
}
else if (argv[0][1] == 'o') {
shift;
ofslen = bytesize(*argv);
}
else if (argv[0][1] == 'x') {
shift;
ofslen = strtol(*argv, (char **)NULL, 0);
}
else if (argv[0][1] == 'y') {
shift;
ofslen = strtol(*argv, (char **)NULL, 0) - FORMOFS;
}
else if (argv[0][1] == 'e') {
chkeof = !chkeof;
}
else if (argv[0][1] == 'p') {
shift;
strcpy(path, *argv);
}
else if (argv[0][1] == 'v') {
++verbose;
}
else {
usage();
exit(1);
}
shift;
}
if (blksiz <= 0) {
blksiz = BLKSIZ;
}
if (minlen <= 0) {
minlen = MINLEN;
}
if (maxlen <= 0) {
maxlen = MAXLEN;
}
if (ofslen < 0) {
ofslen = OFSLEN;
}
if ((strlen(path) > 0) && (path[strlen(path) - 1] != '/')) {
strcat(path, "/");
}
if (argc > 0) {
while (argc > 0) {
if ((fp = fopen(*argv, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
exit(1);
}
if (verbose > 0) {
fprintf(stderr,
"%s: file %s, -b=%d -s=%d -l=%d -o=%d -e=%d -p=%s\n",
prog, *argv, blksiz, minlen, maxlen, ofslen,
chkeof, path);
}
salvage(fp, blksiz, minlen, maxlen, ofslen,
imgsiz, chkeof, path, verbose);
shift;
}
}
else {
salvage(stdin, blksiz, minlen, maxlen, ofslen,
imgsiz, chkeof, path, verbose);
}
exit(0);
}
/* Local Variables: */
/* compile-command:"cc -Wall -o exifrescue exifrescue.c" */
/* End: */