diff options
| author | Stef Walter <stef@thewalter.net> | 2004-04-03 05:42:49 +0000 | 
|---|---|---|
| committer | Stef Walter <stef@thewalter.net> | 2004-04-03 05:42:49 +0000 | 
| commit | 94ba99e2ccdfaf862af6ce039ae447eb244c9283 (patch) | |
| tree | fad6b3e2d9fd1c80012d7e80a6713ea3d294e6eb /src | |
| parent | de5167a304b5e3b2db7462329334ac01d492d72c (diff) | |
Prep for unix porting
Diffstat (limited to 'src')
| -rw-r--r-- | src/compat.c | 241 | ||||
| -rw-r--r-- | src/compat.h | 204 | ||||
| -rw-r--r-- | src/drive.h | 6 | ||||
| -rw-r--r-- | src/list.c | 20 | ||||
| -rw-r--r-- | src/main.c | 60 | ||||
| -rw-r--r-- | src/memref.h | 8 | ||||
| -rw-r--r-- | src/misc.c | 75 | ||||
| -rw-r--r-- | src/ntfs.h | 4 | ||||
| -rw-r--r-- | src/ntfsx.c | 2 | ||||
| -rw-r--r-- | src/posix.c | 89 | ||||
| -rw-r--r-- | src/scrounge.c | 88 | ||||
| -rw-r--r-- | src/scrounge.h | 5 | ||||
| -rw-r--r-- | src/unicode.c | 141 | ||||
| -rw-r--r-- | src/win32.c | 10 | 
14 files changed, 643 insertions, 310 deletions
| diff --git a/src/compat.c b/src/compat.c index 5ee1c0e..b183a99 100644 --- a/src/compat.c +++ b/src/compat.c @@ -27,139 +27,6 @@  #include <string.h>  #endif -#ifndef HAVE_TOLOWER -int tolower(int c) -{ -	if('A' <= c && c <= 'Z') -		c += 'a' - 'A'; -	return c; -} -#define HAVE_TOLOWER -#endif - - -#ifndef HAVE_STRDUP - -#ifndef HAVE_MALLOC -#error Need a working malloc. -#endif - -char* strdup(const char* str) -{ -	char* dup = (char*)malloc((strlen(str) + 1) * sizeof(char)); -	if(dup) -		strcpy(dup, str); -	return dup; -} -#define HAVE_STRDUP -#endif - - -#ifndef HAVE_STRNDUP -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -char* strndup(const char* str, size_t cnt) -{ -	char* buff = malloc(sizeof(char) * (cnt + 1)); -	if(buff) -	{ -		memcpy(buff, str, sizeof(char) * cnt); -		buff[cnt] = 0; -	} -	return buff; -} -#endif - - -#ifndef HAVE_STRCASESTR -char* strcasestr(const char* buff, const char* str) -{ -	const char* ptr = buff; - -    while (*ptr != 0x00) -	{ -        const char* one = ptr; -        const char* two = str; - -        while (tolower(*one) == tolower(*two)) -		{ -            one++; -            two++; -            if (*two == 0x00) -				return (char*) ptr; -        } -        ptr++; -    } -    return NULL; -} -#endif - -#ifndef HAVE_STRLCPY - -#ifndef HAVE_STRNCPY -#error neither strncpy or strlcpy found -#endif - -void strlcpy(char* dest, const char* src, size_t count) -{ -	strncpy(dest, src, count); -	dest[count - 1] = 0; -} -#endif - -#ifndef HAVE_STRLCAT - -#ifndef HAVE_STRNCAT -#error neither strncat or strlcat found -#endif - -void strlcat(char* dest, const char* src, size_t count) -{ -	strncat(dest, src, count); -	dest[count - 1] = 0; -} -#endif - - -#ifndef HAVE_VASPRINTF - -#ifndef HAVE_VSNPRINTF -#error neither vasprintf or vsnprintf found -#endif - -int vasprintf(char** ret, const char* format, va_list vl) -{ -	size_t size = 32; -	int c; -	*ret = NULL; - -	do -	{ -		/* Double the buffer size for next time around */ -		size += size; - -		if(*ret) -			free(*ret); - -		*ret = (char*)malloc(sizeof(char) * size); - -		if(!(*ret)) -		{ -			errno = ENOMEM; -			return -1; -		} - -		c = vsnprintf(*ret, size, format, vl); -	} -	while(c < 0); - -	return c; -} - -#endif - -  /*   * We need to get a better check for this one.   * Basically have to make a variable __progname if none @@ -424,24 +291,6 @@ void vwarnx(const char *fmt, va_list ap)  #endif - -#ifndef HAVE_STRLWR - -char* strlwr(char *string) -{ -	char * cp; -	for (cp=string; *cp; ++cp) -    { -		if('A' <= *cp && *cp <= 'Z') -            *cp += 'a' - 'A'; -    } -    return(string); -} - -#endif - - -  #ifndef HAVE_REALLOCF  void* reallocf(void* ptr, size_t size) @@ -455,3 +304,93 @@ void* reallocf(void* ptr, size_t size)  }  #endif + +#ifndef HAVE_ITOW +wchar_t* itow(int val, wchar_t* out, int radix) +{ +  int mod; +  wchar_t temp; +  wchar_t* end = out; +  wchar_t* beg = out; + +  if(val != 0) +  { +    /* If negative and decimal*/ +    if(radix == 10 && val < 0) +      *beg++ = L'-'; + +    /* Convert in reverse order */ +    while(val != 0) +    { +      mod = val % radix; +      val = val / radix; + +      *end++ = (mod < 10) ? L'0' + mod : L'a' + mod - 10; +    } + +    *end-- = 0; + +    /* Reverse output string */ +    while(end > beg) +    { +      temp = *end; +      *end = *beg; +      *beg = temp; +      ++beg; +      --end; +    } +  } +  else +  { +    beg[0] = L'0'; +    beg[1] = 0; +  } + +  return out; +} +#endif + +#ifndef HAVE_ITOA +wchar_t* itow(int val, wchar_t* out, int radix) +{ +  int mod; +  wchar_t temp; +  wchar_t* end = out; +  wchar_t* beg = out; + +  if(val != 0) +  { +    /* If negative and decimal*/ +    if(radix == 10 && val < 0) +      *beg++ = L'-'; + +    /* Convert in reverse order */ +    while(val != 0) +    { +      mod = val % radix; +      val = val / radix; + +      *end++ = (mod < 10) ? L'0' + mod : L'a' + mod - 10; +    } + +    *end-- = 0; + +    /* Reverse output string */ +    while(end > beg) +    { +      temp = *end; +      *end = *beg; +      *beg = temp; +      ++beg; +      --end; +    } +  } +  else +  { +    beg[0] = L'0'; +    beg[1] = 0; +  } + +  return out; +} +#endif
\ No newline at end of file diff --git a/src/compat.h b/src/compat.h index cc3b73e..373d359 100644 --- a/src/compat.h +++ b/src/compat.h @@ -43,16 +43,6 @@  #include <stdarg.h>  #endif - -#ifndef HAVE_STAT -#ifdef _WIN32 -#define S_IFDIR _S_IFDIR -#define HAVE_STAT -#else -#error ERROR: Must have a working 'stat' function -#endif -#endif -  #ifndef HAVE_GETCWD  #ifdef _WIN32  #include <direct.h> @@ -73,44 +63,11 @@  #endif  #endif -#ifndef HAVE_TOLOWER -int tolower(int c); -#endif - -#ifndef HAVE_STRDUP -char* strdup(const char* str); -#endif - -#ifndef HAVE_STRNDUP -char* strndup(const char* str, size_t cnt); -#endif - -#ifndef HAVE_STRCASESTR -char* strcasestr(const char* big, const char* little); -#endif - -#ifndef HAVE_STRCASECMP -#ifdef HAVE_STRICMP -#define strcasecmp stricmp -#else -#error ERROR: Must have either 'strcasecmp' or 'stricmp' -#endif -#endif - -#ifndef HAVE_STRCASECMP -#ifdef HAVE_STRICMP -#define strncasecmp strnicmp -#else -#error ERROR: Must have either 'strncasecmp' or 'strnicmp' -#endif -#endif - -  #ifndef NULL  #define NULL	(void*)0  #endif -#ifndef __cplusplus +#ifndef HAVE_BOOL  typedef unsigned char bool;  #define false	0x00  #define true	0x01 @@ -126,30 +83,6 @@ typedef unsigned int uint;  #define HAVE_UINT  #endif -#ifndef HAVE_STRLCPY -void strlcpy(char* dest, const char* src, size_t count); -#endif - -#ifndef HAVE_STRLCAT -void strlcat(char* dest, const char* src, size_t count); -#endif - -#ifndef HAVE_VSNPRINTF - -#ifdef _WIN32 -#define vsnprintf _vsnprintf -#define HAVE_VSNPRINTF -#else -#ifndef HAVE_VASPRINTF -#error ERROR: Must have a working 'vsnprintf' or 'vasprintf' function -#endif -#endif -#endif - -#ifndef HAVE_VASPRINTF -int vasprintf(char** ret, const char* format, va_list vl); -#endif -  #ifdef HAVE_UNISTD_H  #include <unistd.h>  #endif @@ -182,4 +115,139 @@ void vwarnx(const char *fmt, va_list ap);  void* reallocf(void* ptr, size_t size);  #endif +/* Some number conversion stuff */ + +#ifndef HAVE_ITOW +  #ifdef _WIN32 +    #define itow _itow +    #define HAVE_ITOW 1 +  #else +    wchar_t itow(int v, wchar_t* s, int r); +  #endif +#endif + +#ifndef HAVE_ITOA +  #ifdef _WIN32 +    #define itoa _itoa +    #define HAVE_ITOA 1 +  #else +    char itoa(int v, char* s, int r); +  #endif +#endif + + +/* + * Depending on the OS we use different width characters + * for file names and file access. Before enabling wide + * file access for an OS the printf needs to be able to + * handle wide chars (ie: %S) and there should be wide + * char file access functions + */ + +#ifdef _WIN32 +  /* On windows we use UCS2 */ +  typedef wchar_t fchar_t; +  #define FC_WIDE 1 +  #define FC_PRINTF "%S" +#else +  /* Everywhere else we use UTF-8 */ +  typedef char fchar_t; +  #undef FC_WIDE +  #define FC_PRINTF "%s"  #endif + +#ifdef FC_WIDE + +  /* An OS that handles wide char file access */ + +  #ifdef HAVE_WOPEN +    #define fc_open wopen +  #else +    #ifdef _WIN32 +      #define fc_open _wopen +    #else +      #error Set for wide file access, but no wide open +    #endif +  #endif + +  #ifdef HAVE_WCHDIR +    #define fc_chdir wchdir +  #else +    #ifdef _WIN32 +      #define fc_chdir _wchdir +    #else +      #error Set for wide file access but no wide chdir +    #endif +  #endif + +  #ifdef HAVE_WMKDIR +    #define fc_mkdir wmkdir +  #else +    #ifdef _WIN32 +      #define fc_mkdir _wmkdir +    #else +      #error Set for wide file access but no wide mkdir +    #endif +  #endif + +  #ifdef HAVE_WGETCWD +    #define fc_getcwd wgetcwd +  #else +    #ifdef _WIN32 +      #define fc_getcwd _wgetcwd +    #else +      #error Set for wide file access but no wide getcwd +    #endif +  #endif + +  #define fcscpy wcscpy +  #define fcscat wcscat +  #define fcsncpy wcsncpy +  #define fcslen wcslen +  #define fcscmp wcscmp +  #define itofc itow + +  #define FC_DOT L"." + +#else + +  /* OSs without wide char file access */ + +  #define fc_open open +  #define fc_chdir chdir +  #define fc_mkdir mkdir +  #define fc_getcwd getcwd + +  #define fcscpy strcpy +  #define fcscat strcat +  #define fcslen strlen +  #define fcscmp strcmp +  #define itofc itoa + +  #define FC_DOT "." + +#endif + + + +/* 64 bit file handling stuff */ + +#ifndef HAVE_LSEEK64 +  #ifdef _WIN32 +    #define lseek64 _lseeki64 +  #else +    #ifdef HAVE_64BITOFFT +      #define lseek64 lseek +    #else +      #error ERROR: Must have a working 64 bit seek function +    #endif +  #endif +#endif + +#include <fnctl.h> +#ifdef O_LARGEFILE +  #define OPEN_LARGE_OPTS O_LARGEFILE +#else +  #define OPEN_LARGE_OPTS 0 +#endif + diff --git a/src/drive.h b/src/drive.h index 4c52584..22e7d2d 100644 --- a/src/drive.h +++ b/src/drive.h @@ -83,7 +83,9 @@ drive_mbr;  #define SECTOR_TO_BYTES(sec) ((sec) * kSectorSize)  #define CLUSTER_SIZE(info) ((info).cluster * kSectorSize) -/* driveName should be MAX_PATH chars long */ -void makeDriveName(char* driveName, int i); +#ifdef _WIN32 +  /* driveName should be MAX_PATH chars long */ +  void makeDriveName(char* driveName, int i); +#endif  #endif /* __DRIVE_H__ */ @@ -33,6 +33,7 @@ const char kPrintData[]		= "\  ";  const char kPrintDrive[]		= "\nDrive: %u\n"; +const char kPrintDrivePath[]		= "\nDrive: %s\n";  const char kPrintDriveInfo[]	= "    %-15u %-15u ";  const char kPrintNTFSInfo[]		= "%-15u %-15u"; @@ -45,8 +46,7 @@ int printNTFSInfo(int dd, uint64 tblSector)  	pos = SECTOR_TO_BYTES(tblSector); -  /* PORT: Windows specific */ -  if(_lseeki64(dd, pos, SEEK_SET) == -1) +  if(lseek64(dd, pos, SEEK_SET) == -1)      err(1, "couldn't seek drive");    sz = read(dd, §or, kSectorSize); @@ -75,8 +75,7 @@ int printPartitionInfo(int dd, uint64 tblSector)  	pos = SECTOR_TO_BYTES(tblSector); -  /* PORT: Windows specific */ -  if(_lseeki64(dd, pos, SEEK_SET) == -1) +  if(lseek64(dd, pos, SEEK_SET) == -1)      err(1, "couldn't seek drive");    sz = read(dd, &mbr, sizeof(drive_mbr)); @@ -120,7 +119,7 @@ void scroungeList()  	{      makeDriveName(driveName, i); -    dd = open(driveName, _O_BINARY | _O_RDONLY); +    dd = open(driveName, _O_BINARY | _O_RDONLY | OPEN_LARGE_OPTS);      if(dd != -1)      {  			printf(kPrintDrive, i); @@ -129,3 +128,14 @@ void scroungeList()  		}  	}  } + +void scroungeListDrive(char* drive) +{ +  int dd = open(driveName, _O_BINARY | _O_RDONLY | OPEN_LARGE_OPTS; +  if(dd == -1) +    err(1, "couldn't open drive: %s", driveName); + +  printf(kPrintDrivePath, driveName); +  printPartitionInfo(dd, 0); +  close(dd); +} @@ -27,6 +27,8 @@  #include "scrounge.h"  #include "compat.h" +#ifdef _WIN32 +  const char kPrintHelp[]       = "\  usage: scrounge -l                                                   \n\    List all drive partition information.                              \n\ @@ -45,6 +47,28 @@ usage: scrounge [-d drive] [-m mftoffset] [-c clustersize] [-o outdir] start end                                                                       \n\  "; +#else /* Not WIN32 */ + +const char kPrintHelp[]       = "\ +usage: scrounge -l                                                   \n\ +  List all drive partition information.                              \n\ +                                                                     \n\ +usage: scrounge -s disk                                              \n\ +  Search drive for NTFS partitions.                                  \n\ +                                                                     \n\ +usage: scrounge [-m mftoffset] [-c clustersize] [-o outdir] disk start end  \n\ +  Scrounge data from a partition                                     \n\ +  -m         Offset to mft (in sectors)                              \n\ +  -c         Cluster size (in sectors, default of 8)                 \n\ +  -o         Directory to put scrounged files in                     \n\ +  disk       The raw disk partitios (ie: /dev/hda)                   \n\ +  start      First sector of partition                               \n\ +  end        Last sector of partition                                \n\ +                                                                     \n\ +"; + +#endif +  #define MODE_SCROUNGE 1  #define MODE_LIST     2  #define MODE_SEARCH   3  @@ -58,16 +82,22 @@ int main(int argc, char* argv[])    int temp = 0;    int mode = 0;    int raw = 0; -  int drive = 0;    partitioninfo pi;    char driveName[MAX_PATH]; +#ifdef _WIN32 +  int drive = 0; +#endif    memset(&pi, 0, sizeof(pi));    /* TODO: We need to be able to autodetect the cluster size */    pi.cluster = 8; +#ifdef _WIN32    while((ch = getopt(argc, argv, "c:d:hlm:o:s")) != -1) +#else +  while((ch = getopt(argc, argv, "c:hlm:o:s")) != -1) +#endif    {      switch(ch)      { @@ -86,6 +116,7 @@ int main(int argc, char* argv[])        }        break; +#ifdef _WIN32      /* drive number */      case 'd':        { @@ -98,6 +129,7 @@ int main(int argc, char* argv[])          drive = temp;        }        break; +#endif      /* help mode */      case 'h': @@ -156,6 +188,21 @@ int main(int argc, char* argv[])    argc -= optind;    argv += optind; +#ifdef _WIN32 +  /* Under windows we format the drive number */ +  makeDriveName(driveName, drive); + +#else +  /* Now when not under Windows, it's the drive name */ +  if(argc < 1) +    errx(2, "must specify drive name"); + +  driveName = argv[0]; +  argv++; +  argc--; +#endif + +    if(mode == MODE_SCROUNGE || mode == 0)    {      /* Get the sectors */ @@ -178,11 +225,10 @@ int main(int argc, char* argv[])      pi.end = temp; -    makeDriveName(driveName, drive); - -    pi.device = open(driveName, _O_BINARY | _O_RDONLY); +    /* Open the device */ +    pi.device = open(driveName, _O_BINARY | _O_RDONLY | OPEN_LARGE_OPTS);      if(pi.device == -1) -      err(1, "couldn't open drive"); +      err(1, "couldn't open drive: %s", driveName);      /* Use mft type search */      if(pi.mft != 0) @@ -205,7 +251,11 @@ int main(int argc, char* argv[])      /* List partition and drive info */      if(mode == MODE_LIST) +#ifdef _WIN32        scroungeList(); +#else +      scroungeListDrive(driveName); +#endif      /* Search for NTFS partitions */      if(mode == MODE_SEARCH) diff --git a/src/memref.h b/src/memref.h index 1138b63..270b8e4 100644 --- a/src/memref.h +++ b/src/memref.h @@ -23,8 +23,8 @@  #ifdef _DEBUG  void* _refalloc_dbg(size_t sz); -void* _refadd_dbg(void* pBuff); -void _refrelease_dbg(void* pBuff); +void* _refadd_dbg(void* buf); +void _refrelease_dbg(void* buf);  #define refalloc	_refalloc_dbg  #define refadd		_refadd_dbg @@ -33,8 +33,8 @@ void _refrelease_dbg(void* pBuff);  #else  void* _refalloc(size_t sz); -void* _refadd(void* pBuff); -void _refrelease(void* pBuff); +void* _refadd(void* buf); +void _refrelease(void* buf);  #define refalloc	_refalloc  #define refadd		_refadd @@ -42,12 +42,13 @@ void addLocationLock(drivelocks* locks, uint64 beg, uint64 end)  	if(locks->_count <= locks->_current)  	{  		locks->_count += 0x400; -		locks->_locks = (struct drivelock*)realloc(locks->_locks, sizeof(struct drivelock) * locks->_count); -	} +		locks->_locks = (struct drivelock*)reallocf(locks->_locks, sizeof(struct drivelock) * locks->_count); +   +    if(!locks->_locks) +      errx(1, "out of memory"); +  }  	/* TODO: Implement a more efficient method here! */ -  /* TODO: What happens when the above memory allocation fails? */ -  	if(locks->_locks)  	{  		/* Go through and check for a current lock we can tag onto */ @@ -114,80 +115,82 @@ const size_t kRefSig = 0x1F2F3F4F;  void* _refalloc_dbg(size_t sz)  {  	/* Allocate extra counter value before memory */ -	size_t* pMem = (size_t*)malloc(sz * sizeof(size_t) * 2); +	size_t* mem = (size_t*)malloc(sz * sizeof(size_t) * 2); -	if(pMem) +	if(mem)  	{ -		pMem[0] = kRefSig; -		pMem[1] = 1; -		return pMem + 2; +		mem[0] = kRefSig; +		mem[1] = 1; +		return mem + 2;  	} -	return pMem; +	return mem;  }  #endif   void* _refalloc(size_t sz)  {  	/* Allocate extra counter value before memory */ -	size_t* pMem = (size_t*)malloc(sz * sizeof(size_t) * 1); +	size_t* mem = (size_t*)malloc(sz * sizeof(size_t) * 1); -	if(pMem) +	if(mem)  	{ -		pMem[0] = 1; -		return pMem + 1; +		mem[0] = 1; +		return mem + 1;  	} -	return pMem; +	return mem;  }  #ifdef _DEBUG -void* _refadd_dbg(void* pBuff) +void* _refadd_dbg(void* buf)  { -	if(pBuff) +	if(buf)  	{  		/* Increment the counter value */ -		size_t* pMem = (size_t*)pBuff - 2; -		assert(pMem[0] == kRefSig); -		pMem[1]++; +		size_t* mem = (size_t*)buf - 2; +		assert(mem[0] == kRefSig); +		mem[1]++;  	} -	return pBuff; +	return buf;  }  #endif -void* _refadd(void* pBuff) +void* _refadd(void* buf)  { -	if(pBuff) +	if(buf)  		/* Increment the counter value */ -		((size_t*)pBuff)[-1]++; +		((size_t*)buf)[-1]++; -	return pBuff; +	return buf;  }  #ifdef _DEBUG -void _refrelease_dbg(void* pBuff) +void _refrelease_dbg(void* buf)  { -	if(pBuff) +	if(buf)  	{  		/* Decrement the counter value */ -		size_t* pMem = (size_t*)pBuff - 2; -		assert(pMem[0] == kRefSig); +		size_t* mem = (size_t*)buf - 2; +		assert(mem[0] == kRefSig); -		if(!--pMem[1]) -			free(pMem); +		if(!--mem[1]) +			free(mem);  	}  }  #endif -void _refrelease(void* pBuff) +void _refrelease(void* buf)  { -	if(pBuff) +	if(buf)  	{  		/* Decrement the counter value */ -		size_t* pMem = (size_t*)pBuff - 1; +		size_t* mem = (size_t*)buf - 1; -		if(!--pMem[0]) -			free(pMem); +		if(!--mem[0]) +			free(mem);  	}  } + + @@ -191,4 +191,8 @@ byte* ntfs_getattributedata(ntfs_attribresident* attrib, byte* end);  bool ntfs_isbetternamespace(byte n1, byte n2);  bool ntfs_dofixups(byte* cluster, uint32 size); +/* TODO: Move these declarations elsewhere */ +char* unicode_transcode16to8(const wchar_t* src, size_t len); +wchar_t* unicode_transcode8to16(const char* src, const wchar_t* out, size_t len); +  #endif /* __NTFS_H__ */ diff --git a/src/ntfsx.c b/src/ntfsx.c index 8910f89..a3209e1 100644 --- a/src/ntfsx.c +++ b/src/ntfsx.c @@ -420,7 +420,7 @@ bool ntfsx_mftmap_load(ntfsx_mftmap* map, ntfsx_record* record, int dd)          if(map->_count >= allocated)          {            allocated += 16; -          map->_blocks = (struct _ntfsx_mftmap_block*)realloc(map->_blocks,  +          map->_blocks = (struct _ntfsx_mftmap_block*)reallocf(map->_blocks,                     allocated * sizeof(struct _ntfsx_mftmap_block));            if(!(map->_blocks))        			errx(1, "out of memory"); diff --git a/src/posix.c b/src/posix.c new file mode 100644 index 0000000..0586715 --- /dev/null +++ b/src/posix.c @@ -0,0 +1,89 @@ +/*  + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * 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 author(s) 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. + *  + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + + +#include "usuals.h" +#include "ntfs.h" + +/* NOTE: This file assumes that FC_WIDE is off */ + +/* The NTFS file time is a a 64-bit value representing the  +   number of 100-nanosecond intervals since January 1, 1601 */ + +/* The unix epoch in NTFS ft */ +#define UNIX_EPOCH    116444736000000000LL + +void ntfs_maketvs(uint64* ft, struct timeval* tv) +{ +  /* Anything before the unix epoch is stupid */ +  if(*ft < UNIX_EPOCH) +  { +    tv->tv_sec = 0; +    tv->tv_usec = 0; +  } + +  /* Anything later than we can represent is a bummer */ +  else if(sizeof(tv->tv_sec) == 32) +  { +    tv->tv_sec = 0x7FFFFFFF; +    tv->tv_usec = 0x7FFFFFFF; +  } + +  /* Now convert the valid range of dates */ +  else +  { +    uint mod = (*ft % 1000000000); +    tv->tv_sec = ((*ft - mod) / 1000000000); +    tv->tv_usec = mod / 1000; +  } +}; + +void setFileTime(fchar_t* filename, uint64* created,  +                  uint64* accessed, uint64* modified) +{ +  int r; +  struct timeval tvs[2]; +  char* encoded; + +  ntfs_maketvs(accessed, tvs); +  ntfs_maketvs(modified, tvs + 1); +  if(utimes(filename, tvs) == -1) +    warn("couldn't set file times on: %s", encoded); +} + +void setFileAttributes(fchar_t* filename, uint32 flags) +{ +  char* encoded; +  struct stat st; + +  if(flags & kNTFS_FileReadOnly) +  { +    if(stat(filename, &st) == -1) +    { +      warn("couldn't read file status for: " FC_PRINTF, encoded); +    } +    else +    { +      if(chmod(filename, st.st_mode & ~(S_IWUSR | S_IWGRP | S_IOTH)) == -1) +        warn("couldn't set file attributes for: " FC_PRINTF, encoded); +    } +  } +} + + diff --git a/src/scrounge.c b/src/scrounge.c index f4436de..66297a8 100644 --- a/src/scrounge.c +++ b/src/scrounge.c @@ -30,7 +30,7 @@  typedef struct _filebasics  { -  wchar_t filename[MAX_PATH + 1]; +  fchar_t filename[MAX_PATH + 1];    uint64 created;    uint64 modified;    uint64 accessed; @@ -48,6 +48,11 @@ void processRecordFileBasics(partitioninfo* pi, ntfsx_record* record, filebasics      byte* resident = NULL;      ntfs_attribfilename* filename;      byte nameSpace; +    wchar_t* name; +    size_t len; +#ifndef FC_WIDE +    char* temp; +#endif      ASSERT(record);      memset(basics, 0, sizeof(filebasics)); @@ -82,15 +87,36 @@ void processRecordFileBasics(partitioninfo* pi, ntfsx_record* record, filebasics          basics->accessed = filename->timeRead;  				/* File Name */ -				wcsncpy(basics->filename, (wchar_t*)(((byte*)filename) + sizeof(ntfs_attribfilename)), filename->cFileName); -				basics->filename[filename->cFileName] = 0; +        name = (wchar_t*)(((byte*)filename) + sizeof(ntfs_attribfilename)); +        len = filename->cFileName; +        if(len > MAX_PATH) +          len = MAX_PATH; + +#ifdef FC_WIDE +        wcsncpy(basics->filename, name, len); +#else +        temp = unicode_transcode16to8(basics->filename, len); +        if(!temp) +          errx(1, "out of memory"); + +        len = strlen(temp); +        if(len > MAX_PATH) +          len = MAX_PATH; +         +        strncpy(basics->filename, temp, len); +#endif + +        basics->filename[len] = 0; +  				/* Attributes */          basics->flags = filename->flags; +  				/* Parent Directory */          basics->parent = filename->refParent & 0xFFFFFFFFFFFF; +  				/* Namespace */  				nameSpace = filename->nameSpace;  			} @@ -122,7 +148,7 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)      uint64 fileSize;      uint32 i;      uint32 num; -    wchar_t filename2[MAX_PATH + 1]; +    fchar_t filename2[MAX_PATH + 1];      ntfs_attribheader* attrhead;      ntfs_attribnonresident* nonres; @@ -151,7 +177,7 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)      }      /* If it's the root folder then return */ -    if(!wcscmp(basics.filename, L".")) +    if(!fcscmp(basics.filename, FC_DOT))        RETURN;      /* Process parent folders if available */ @@ -163,30 +189,28 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)          parentSector = ntfsx_mftmap_sectorforindex(pi->mftmap, basics.parent);          if(parentSector == kInvalidSector) -          warnx("invalid parent directory for file: %S", basics.filename); +          warnx("invalid parent directory for file: " FC_PRINTF, basics.filename);          else            processMFTRecord(pi, parentSector, level + 1);        }      } -    printf(level == 0 ? "\\%S\n" : "\\%S", basics.filename); +    printf(level == 0 ? "\\" FC_PRINTF "\n" : "\\" FC_PRINTF, basics.filename);      /* Directory handling: */      if(header->flags & kNTFS_RecFlagDir)      {        /* Try to change to the directory */ -      /* PORT: Wide character file functions */ -      if(_wchdir(basics.filename) == -1) +      if(wchdir(basics.filename) == -1)        { -        /* PORT: Wide character file functions */ -        if(_wmkdir(basics.filename) == -1) +        if(wmkdir(basics.filename) == -1)          { -          warnx("couldn't create directory '%S' putting files in parent directory", basics.filename); +          warnx("couldn't create directory '" FC_PRINTF "' putting files in parent directory", basics.filename);          }          else          {            setFileAttributes(basics.filename, basics.flags); -          _wchdir(basics.filename); +          wchdir(basics.filename);          }        } @@ -195,32 +219,31 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)      /* Normal file handling: */ -    /* PORT: Wide character file functions */ -    outfile = _wopen(basics.filename, _O_BINARY | _O_CREAT | _O_EXCL | _O_WRONLY); +    outfile = wopen(basics.filename, _O_BINARY | _O_CREAT | _O_EXCL | _O_WRONLY); -    wcsncpy(filename2, basics.filename, MAX_PATH); +    fcsncpy(filename2, basics.filename, MAX_PATH);      filename2[MAX_PATH] = 0;      while(outfile == -1 && errno == EEXIST && rename < 0x1000)      { -      if(wcslen(basics.filename) + 7 >= MAX_PATH) +      if(fcslen(basics.filename) + 7 >= MAX_PATH)        { -        warnx("file name too long on duplicate file: %S", basics.filename); +        warnx("file name too long on duplicate file: " FC_PRINTF, basics.filename);          goto cleanup;        } -      wcscpy(basics.filename, filename2); -      wcscat(basics.filename, L"."); +      fcscpy(basics.filename, filename2); +      fcscat(basics.filename, L"."); -      _itow(rename, basics.filename + wcslen(basics.filename), 10); +      itofc(rename, basics.filename + fcslen(basics.filename), 10);        rename++; -      outfile = _wopen(basics.filename, _O_BINARY | _O_CREAT | _O_EXCL | _O_WRONLY); +      outfile = fc_open(basics.filename, _O_BINARY | _O_CREAT | _O_EXCL | _O_WRONLY);      }      if(outfile == -1)      { -      warnx("couldn't open output file: %S", basics.filename); +      warnx("couldn't open output file: " FC_PRINTF, basics.filename);        goto cleanup;      } @@ -282,7 +305,7 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)                  num = (uint32)fileSize;                if(write(outfile, cluster.data, num) != (int32)num) -                err(1, "couldn't write to output file: %S", basics.filename); +                err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);                fileSize -= num;              } @@ -308,7 +331,7 @@ void processMFTRecord(partitioninfo* pi, uint64 sector, int level)                  err(1, "couldn't read sector from disk");                if(write(outfile, cluster.data, num) != (int32)num) -                err(1, "couldn't write to output file: %S", basics.filename); +                err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);                fileSize -= num;              } @@ -378,7 +401,7 @@ void scroungeMFT(partitioninfo* pi, ntfsx_mftmap* map)    processRecordFileBasics(pi, record, &basics); -  if(wcscmp(basics.filename, kNTFS_MFTName)) +  if(fcscmp(basics.filename, kNTFS_MFTName))      errx(2, "invalid mft. wrong record");    fprintf(stderr, "[Processing MFT...]\n"); @@ -398,7 +421,7 @@ void scroungeMFT(partitioninfo* pi, ntfsx_mftmap* map)  void scroungeUsingMFT(partitioninfo* pi)  {  	uint64 numRecords = 0; -	char dir[MAX_PATH]; +	fchar_t dir[MAX_PATH];    ntfsx_mftmap map;    uint64 length;    uint64 sector; @@ -407,7 +430,7 @@ void scroungeUsingMFT(partitioninfo* pi)    fprintf(stderr, "[Scrounging via MFT...]\n");  	/* Save current directory away */ -	getcwd(dir, MAX_PATH); +	fc_getcwd(dir, MAX_PATH);    /* Get the MFT map ready */    memset(&map, 0, sizeof(map)); @@ -435,7 +458,7 @@ void scroungeUsingMFT(partitioninfo* pi)      processMFTRecord(pi, sector, 0);    	/* Move to right output directory */ -    chdir(dir); +    fc_chdir(dir);  	}    pi->mftmap = NULL; @@ -444,7 +467,7 @@ void scroungeUsingMFT(partitioninfo* pi)  void scroungeUsingRaw(partitioninfo* pi)  {  	byte buffSec[kSectorSize]; -	char dir[_MAX_PATH + 1]; +	fchar_t dir[_MAX_PATH + 1];    uint64 sec;    drivelocks locks;    int64 pos; @@ -454,7 +477,7 @@ void scroungeUsingRaw(partitioninfo* pi)    fprintf(stderr, "[Scrounging raw records...]\n");  	/* Save current directory away */ -	getcwd(dir, _MAX_PATH); +	fc_getcwd(dir, _MAX_PATH);    /* Get the locks ready */    memset(&locks, 0, sizeof(locks)); @@ -481,6 +504,9 @@ void scroungeUsingRaw(partitioninfo* pi)        /* Process the record */        processMFTRecord(pi, sec, 0);  		} + +  	/* Move to right output directory */ +    fc_chdir(dir);  	}    pi->locks = NULL; diff --git a/src/scrounge.h b/src/scrounge.h index 9baf720..b1425fd 100644 --- a/src/scrounge.h +++ b/src/scrounge.h @@ -24,11 +24,12 @@  void scroungeSearch(partitioninfo* pi);  void scroungeList(); +void scroungeListDrive(char* drive);  void scroungeUsingMFT(partitioninfo* pi);  void scroungeUsingRaw(partitioninfo* pi);  /* For compatibility */ -void setFileAttributes(wchar_t* filename, uint32 flags); -void setFileTime(wchar_t* filename, uint64* created, uint64* accessed, uint64* modified); +void setFileAttributes(fchar_t* filename, uint32 flags); +void setFileTime(fchar_t* filename, uint64* created, uint64* accessed, uint64* modified);  #endif /* __SCROUNGE_H__ */ diff --git a/src/unicode.c b/src/unicode.c new file mode 100644 index 0000000..a8fc612 --- /dev/null +++ b/src/unicode.c @@ -0,0 +1,141 @@ + +#include <wchar.h> + +#include <wchar.h> +#include "sablo.h" + +/* + * Transcode UCS2 to UTF8.  + * + * Since the nature of the transformation is that the  + * resulting length is unpredictable, this function + * allocates it's own memory. + */ +char* unicode_transcode16to8(const wchar_t* src, size_t len) +{ +  char* ret = NULL; +  size_t alloc = 0; +  size_t pos = 0; +  const wchar_t* c; +  const wchar_t* e; + +  /* Allocate 1.25 times the length initially */ +  alloc = len + (len / 4) + 1; +  ret = (char*)malloc(alloc * sizeof(char)); +  if(!ret) return NULL; + +  c = src; +  e = c + len; + +  for( ; c < e; c++) +  { +    /* Make sure we have enough memory */ +    if(pos + 4 >= alloc) +    { +      alloc += (len / 2) + 1; +      if(!(ret = (char*)reallocf(ret, alloc * sizeof(char)))) +        return NULL; +    } + +    /* Encode as one character */ +    if(*c <= 0x007F) +    { +      ret[pos++] = (char)*c; +    } + +    /* Encode as two characters */ +    else if(*c <= 0x07FF) +    { +      ret[pos++] = (char)(192 | (*c >> 6)); +      ret[pos++] = (char)(128 | (*c & 63)); +    } + +    /* Encode as three characters */ +    else  +    { +      ret[pos++] = (char)(224 | (*c >> 12)); +      ret[pos++] = (char)(128 | ((*c >> 6) & 63)); +      ret[pos++] = (char)(128 | (*c & 63)); +    } +  } + +  ret[pos] = NULL; +  return ret; +} + +/* + * Transcode UTF-8 to UCS2 + *  + * Since a semi predictable length of the resulting data is  + * known, the caller should allocate the memory for this conversion. + */ +wchar_t* unicode_transcode8to16(const char* src, const wchar_t* out, size_t len) +{ +  /* Note: out should always be at least as long as src in chars */ + +  size_t pos = 0; +  const char* c; +  const char* e; + +  c = src; +  e = c + len; + +  for( ; c < e; c++) +  { +    /* We never have to reallocate here. We will always +       be using the same or less number of output characters  +       than input chars. That's just the nature of the encoding. */ +     +    /* First 4 bits set */ +    if((c + 3) < e &&  +       (c[0] & 0xF8) == 0xF0 &&  +       (c[1] & 0xC0) == 0x80 && +       (c[2] & 0xC0) == 0x80 && +       (c[3] & 0xC0) == 0x80) +    { +      out[pos++] = (wchar_t)(((wchar_t)c[0] & 7) << 18 | +                             ((wchar_t)c[1] & 63) << 12 | +                             ((wchar_t)c[2] & 63) << 6 | +                             ((wchar_t)c[3] & 63)); +      c += 3; +    } + +    /* First 3 bits set */ +    else if((c + 2) < e &&  +            (c[0] & 0xF0) == 0xE0 && +            (c[1] & 0xC0) == 0x80 && +            (c[2] & 0xC0) == 0x80) +    { +      out[pos++] = (wchar_t)(((wchar_t)c[0] & 15) << 12 | +                             ((wchar_t)c[1] & 63) << 6 | +                             ((wchar_t)c[2] & 63)); +      c += 2; +    } + +    /* First 2 bits set */ +    else if((c + 1) < e &&  +            (c[0] & 0xE0) == 0xC0 && +            (c[1] & 0xC0) == 0x80) +    { +      out[pos++] = (wchar_t)(((wchar_t)c[0] & 31) << 6 | +                             ((wchar_t)c[1] & 63)); +      c += 1; +    } + +    /* First bit set */ +    else if(!(c[0] & 0x80))   +    { +      out[pos++] = (wchar_t)c[0]; +    } + +    /* Invalid encoding */ +    else +    { +      out[pos++] = L'?'; +    } +  } + +  out[pos] = NULL; +  return out; +} + diff --git a/src/win32.c b/src/win32.c index 0726fad..3cb5b25 100644 --- a/src/win32.c +++ b/src/win32.c @@ -33,7 +33,7 @@ void makeDriveName(char* driveName, int i)    wsprintf(driveName, kDriveName, i);  } -void setFileTime(wchar_t* filename, uint64* created,  +void setFileTime(fchar_t* filename, uint64* created,                     uint64* accessed, uint64* modified)  {    FILETIME ftcr; @@ -49,17 +49,17 @@ void setFileTime(wchar_t* filename, uint64* created,  	file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);    if(file == INVALID_HANDLE_VALUE)    { -    warnx("couldn't set file time: %S", filename); +    warnx("couldn't set file time: " FC_PRINTF, filename);      return;    }    if(!SetFileTime(file, &ftcr, &ftac, &ftmd)) -    warnx("couldn't set file time: %S", filename); +    warnx("couldn't set file time: " FC_PRINTF, filename);    CloseHandle(file);  } -void setFileAttributes(wchar_t* filename, uint32 flags) +void setFileAttributes(fchar_t* filename, uint32 flags)  {    DWORD attributes; @@ -74,5 +74,5 @@ void setFileAttributes(wchar_t* filename, uint32 flags)  		attributes |= FILE_ATTRIBUTE_SYSTEM;    if(!SetFileAttributesW(filename, attributes)) -    warnx("couldn't set file attributes: %S", filename); +    warnx("couldn't set file attributes: " FC_PRINTF, filename);  } | 
