|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 using System; |
|
18 using System.Collections.Generic; |
|
19 using System.Text; |
|
20 using System.IO; |
|
21 using SymbianUtils.Tracer; |
|
22 using SymbianUtils.Streams; |
|
23 using SymbianStructuresLib.Uids; |
|
24 using SymbianStructuresLib.Version; |
|
25 |
|
26 namespace SymbianImageLib.ROFS.Structures |
|
27 { |
|
28 internal class TRofsDir : IEnumerable<TRofsEntry> |
|
29 { |
|
30 #region Constructors |
|
31 public TRofsDir( string aName, uint aFileAddress, SymbianStreamReaderLE aReader, ITracer aTracer ) |
|
32 { |
|
33 //aTracer.Trace( "[Dir ] @ 0x{0:x8} {1}", aFileAddress, aName ); |
|
34 // |
|
35 iName = aName; |
|
36 // |
|
37 aReader.Seek( aFileAddress, SeekOrigin.Begin ); |
|
38 // |
|
39 iStructSize = aReader.ReadUInt16(); |
|
40 iPadding = aReader.ReadUInt8(); |
|
41 iFirstEntryOffset = aReader.ReadUInt8(); |
|
42 iFileBlockAddress = aReader.ReadUInt32(); |
|
43 iFileBlockSize = aReader.ReadUInt32(); |
|
44 // |
|
45 if ( iFileBlockAddress != 0 ) |
|
46 { |
|
47 // Directory has files in it |
|
48 AddFiles( aReader, aTracer, iFileBlockAddress, iFileBlockSize ); |
|
49 } |
|
50 if ( iStructSize > KMinimumDirectoryEntrySize ) |
|
51 { |
|
52 // Directory has subdirectories |
|
53 AddSubDirs( aReader, aTracer, aFileAddress + iStructSize ); |
|
54 } |
|
55 } |
|
56 #endregion |
|
57 |
|
58 #region API |
|
59 #endregion |
|
60 |
|
61 #region Constants |
|
62 // The minimum standard entry size, irrespective of whether the directory |
|
63 // contains subdirs or files. |
|
64 public const uint KMinimumDirectoryEntrySize = 2 + 1 + 1 + 4 + 4; |
|
65 #endregion |
|
66 |
|
67 #region Properties |
|
68 public uint Size |
|
69 { |
|
70 get { return iStructSize; } |
|
71 } |
|
72 |
|
73 public string Name |
|
74 { |
|
75 get { return iName; } |
|
76 } |
|
77 |
|
78 public uint FirstEntryOffset |
|
79 { |
|
80 get { return iFirstEntryOffset; } |
|
81 } |
|
82 |
|
83 public uint FileBlockAddress |
|
84 { |
|
85 get { return iFileBlockAddress; } |
|
86 } |
|
87 |
|
88 public uint FileBlockSize |
|
89 { |
|
90 get { return iFileBlockSize; } |
|
91 } |
|
92 |
|
93 public TRofsDir[] SubDirectories |
|
94 { |
|
95 get |
|
96 { |
|
97 return iSubdirectories.ToArray(); |
|
98 } |
|
99 } |
|
100 #endregion |
|
101 |
|
102 #region Internal methods |
|
103 private void AddFiles( SymbianStreamReaderLE aReader, ITracer aTracer, long aStartPosition, uint aSize ) |
|
104 { |
|
105 long originalPosition = aReader.Position; |
|
106 long endPos = aStartPosition + aSize; |
|
107 // |
|
108 long filePosition = aStartPosition; |
|
109 while ( filePosition < endPos ) |
|
110 { |
|
111 // Seek to start of file and read it |
|
112 aReader.Seek( filePosition, SeekOrigin.Begin ); |
|
113 TRofsEntry entry = new TRofsEntry( aReader, aTracer ); |
|
114 iFiles.Add( entry ); |
|
115 //aTracer.Trace( "[File] @ 0x{0:x8} {1:d8} {2}", filePosition, entry.FileSize, entry.Name ); |
|
116 |
|
117 // Move to next file |
|
118 filePosition += entry.Size; |
|
119 } |
|
120 |
|
121 // Restore original position |
|
122 aReader.Seek( originalPosition, SeekOrigin.Begin ); |
|
123 } |
|
124 |
|
125 private void AddSubDirs( SymbianStreamReaderLE aReader, ITracer aTracer, long aEndDirPos ) |
|
126 { |
|
127 long originalPosition = aReader.Position; |
|
128 // |
|
129 long filePosition = aReader.BaseStream.Position; |
|
130 while ( filePosition < aEndDirPos ) |
|
131 { |
|
132 // Seek to start of subdir and read basic properties |
|
133 aReader.Seek( filePosition, SeekOrigin.Begin ); |
|
134 TRofsEntry entry = new TRofsEntry( aReader, aTracer ); |
|
135 |
|
136 // Create a new subdirectory that we'll process recursively. |
|
137 TRofsDir subdir = new TRofsDir( entry.Name, entry.FileAddress, aReader, aTracer ); |
|
138 iSubdirectories.Add( subdir ); |
|
139 |
|
140 // Move to next subdir, rounding to 4 bytes |
|
141 long nextSubDirOffset = entry.Size; |
|
142 nextSubDirOffset += ( ( 4 - nextSubDirOffset ) & 0x3 ); |
|
143 filePosition += nextSubDirOffset; |
|
144 } |
|
145 |
|
146 // Restore original position |
|
147 aReader.Seek( originalPosition, SeekOrigin.Begin ); |
|
148 } |
|
149 #endregion |
|
150 |
|
151 #region From IEnumerable<TRofsEntry> |
|
152 public IEnumerator<TRofsEntry> GetEnumerator() |
|
153 { |
|
154 foreach ( TRofsEntry entry in iFiles ) |
|
155 { |
|
156 yield return entry; |
|
157 } |
|
158 } |
|
159 |
|
160 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() |
|
161 { |
|
162 foreach ( TRofsEntry entry in iFiles ) |
|
163 { |
|
164 yield return entry; |
|
165 } |
|
166 } |
|
167 #endregion |
|
168 |
|
169 #region Data members |
|
170 private readonly string iName; |
|
171 private ushort iStructSize; // Total size of this directory block including padding |
|
172 private byte iPadding; |
|
173 private byte iFirstEntryOffset; // offset to first entry |
|
174 private uint iFileBlockAddress; // address of associated file block |
|
175 private uint iFileBlockSize; // size of associated file block |
|
176 |
|
177 private List<TRofsEntry> iFiles = new List<TRofsEntry>(); |
|
178 private List<TRofsDir> iSubdirectories = new List<TRofsDir>(); |
|
179 #endregion |
|
180 } |
|
181 } |