summaryrefslogtreecommitdiff
path: root/src/ntfs.c
blob: 28b4cca2a9257e9507245432da00f83da17c540f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// 
// AUTHOR
// N. Nielsen
//
// VERSION
// 0.7
// 
// 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"

#include "malloc.h"
#include "string.h"


NTFS_AttribHeader* NTFS_SearchAttribute(byte* pLocation, uint32 attrType, void* pEnd, bool bSkip)
{
	// Now we should be at attributes
	while((!pEnd || (pLocation + sizeof(NTFS_AttribHeader) < pEnd)) && 
		  *((uint32*)pLocation) != kNTFS_RecEnd)
	{
		NTFS_AttribHeader* pAttrib = (NTFS_AttribHeader*)pLocation;

		if(!bSkip)
		{
			if(pAttrib->type == attrType)
				return pAttrib;
		}
		else
			bSkip = false;

		pLocation += pAttrib->cbAttribute;
	}

	return NULL;
}


NTFS_AttribHeader* NTFS_FindAttribute(NTFS_RecordHeader* pRecord, uint32 attrType, void* pEnd)
{
	byte* pLocation = (byte*)pRecord;
	pLocation += kNTFS_RecHeaderLen;

	return NTFS_SearchAttribute(pLocation, attrType, pEnd, false);
}

NTFS_AttribHeader* NTFS_NextAttribute(NTFS_AttribHeader* pAttrib, uint32 attrType, void* pEnd)
{
	return NTFS_SearchAttribute((byte*)pAttrib, attrType, pEnd, true);
}

void* NTFS_GetAttributeData(NTFS_AttribResident* pAttrib, void* pEnd)
{
	void* pData = ((byte*)pAttrib) + pAttrib->offAttribData;
	if(!pEnd && pData > pEnd)
		return NULL;

	return pData;
}

bool NTFS_IsBetterNameSpace(byte n1, byte n2)
{
	// We like our namespaces in this order
	// 1. WIN32
	// 2. WIN32/DOS
	// 3. DOS
	// 4. POSIX

	if(n1 == kNTFS_NameSpacePOSIX)
		return true;
	if(n1 == kNTFS_NameSpaceDOS &&
	   (n2 == kNTFS_NameSpaceWIN32 || n2 == kNTFS_NameSpaceWINDOS))
	    return true;
	if(n1 == kNTFS_NameSpaceWINDOS &&
	   n2 == kNTFS_NameSpaceWIN32)
	    return true;

	return false;
}

bool NTFS_DoFixups(byte* pCluster, uint32 cbCluster)
{
	ASSERT(cbCluster % kSectorSize == 0);
	NTFS_RecordHeader* pRecord = (NTFS_RecordHeader*)pCluster;

	byte numSectors = (byte)(cbCluster / kSectorSize);

	// Check the number of sectors against array
	if(pRecord->cwUpdSeq - 1 < numSectors)
		numSectors = pRecord->cwUpdSeq - 1;

	uint16* pUpdSeq = (uint16*)(pCluster + pRecord->offUpdSeq);

	for(byte i = 0; i < numSectors; i++)
	{
		// Check last 2 bytes in each sector against
		// first double byte value in update sequence 
		uint16* pSectorFooter = (uint16*)((pCluster + (kSectorSize - 2)) + (i * kSectorSize));
		if(*pSectorFooter == pUpdSeq[0])
			*pSectorFooter = pUpdSeq[i + 1];
		else
			return false;
	}

	return true;
}