|
1 /* |
|
2 * Copyright (c) 2005-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 * System Includes |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <stdio.h> |
|
22 #include <stdlib.h> |
|
23 #ifndef WIN32 |
|
24 #include <unistd.h> |
|
25 #else |
|
26 #include <io.h> |
|
27 #endif |
|
28 #include <errno.h> |
|
29 #include <assert.h> |
|
30 |
|
31 |
|
32 /****************************************************************************************************** |
|
33 * |
|
34 * Local Includes |
|
35 * |
|
36 *****************************************************************************************************/ |
|
37 #include "file_utilities.h" |
|
38 #include "CDynamicsConfigFile.h" |
|
39 |
|
40 |
|
41 /****************************************************************************************************** |
|
42 * |
|
43 * Definition |
|
44 * |
|
45 *****************************************************************************************************/ |
|
46 #define MAXFILENAMESIZE 128 |
|
47 #define MAXLINEPOSITION 99999 |
|
48 #define MAXTOKENMATCHES 16 |
|
49 #define MAXLINESIZE 2048 |
|
50 #ifdef WIN32 |
|
51 #define snprintf _snprintf |
|
52 #endif |
|
53 |
|
54 /****************************************************************************************************** |
|
55 * |
|
56 * PUBLIC METHOD: Constructors |
|
57 * |
|
58 *****************************************************************************************************/ |
|
59 CDynamicsConfigFile::CDynamicsConfigFile() |
|
60 { |
|
61 iStatus = DCS_INIT; |
|
62 iReferenceFilename = ""; |
|
63 iLocalFilename = ""; |
|
64 } |
|
65 |
|
66 |
|
67 CDynamicsConfigFile::~CDynamicsConfigFile() |
|
68 { |
|
69 assert( iStatus != DCS_ACTIVE_LOCAL_COPY ); |
|
70 } |
|
71 |
|
72 |
|
73 /****************************************************************************************************** |
|
74 * |
|
75 * PUBLIC METHOD: SetReferenceFile |
|
76 * |
|
77 *****************************************************************************************************/ |
|
78 TDCFError CDynamicsConfigFile::SetReferenceFile( string aReferenceFile ) |
|
79 { |
|
80 // check that we don't have an active local copy |
|
81 if( iStatus == DCS_ACTIVE_LOCAL_COPY ) { |
|
82 return DCE_INVALID_STATE; |
|
83 } |
|
84 |
|
85 // set the reference file |
|
86 iReferenceFilename = aReferenceFile; |
|
87 iStatus = DCS_REFERENCE_FILE_SET; |
|
88 return DCE_NONE; |
|
89 } |
|
90 |
|
91 |
|
92 /****************************************************************************************************** |
|
93 * |
|
94 * PUBLIC METHOD: CreateLocalCopy |
|
95 * |
|
96 *****************************************************************************************************/ |
|
97 TDCFError CDynamicsConfigFile::CreateLocalCopy( int *aSystemError ) |
|
98 { |
|
99 TFUError ferr; |
|
100 FILE *fp_dest, *fp_source; |
|
101 char copy_filename[MAXFILENAMESIZE]; |
|
102 |
|
103 // check params |
|
104 assert( aSystemError != NULL ); |
|
105 *aSystemError = 0; |
|
106 |
|
107 // check the state |
|
108 if( iStatus != DCS_REFERENCE_FILE_SET ) { |
|
109 return DCE_INVALID_STATE; |
|
110 } |
|
111 |
|
112 // create a tempfile to hold the local copy |
|
113 fp_dest = OpenTempfile( (char*)iReferenceFilename.c_str(), copy_filename, MAXFILENAMESIZE, "w", aSystemError ); |
|
114 if( fp_dest == NULL ) { |
|
115 return DCE_OPEN_TEMP_ERROR; |
|
116 } |
|
117 |
|
118 // open the source file |
|
119 fp_source = fopen( (char*)iReferenceFilename.c_str(), "r" ); |
|
120 if( fp_source == NULL ) { |
|
121 fclose( fp_dest ); |
|
122 unlink( copy_filename ); |
|
123 *aSystemError = errno; |
|
124 return DCE_OPEN_ERROR; |
|
125 } |
|
126 |
|
127 // copy the files, close them, and look for errors |
|
128 ferr = CopyFileByPtr( fp_source, fp_dest, aSystemError ); |
|
129 fflush( fp_source ); |
|
130 fflush( fp_dest ); |
|
131 fclose( fp_source ); |
|
132 fclose( fp_dest ); |
|
133 if( ferr != FUE_NONE ) { |
|
134 unlink( copy_filename ); |
|
135 return (TDCFError)ferr; |
|
136 } |
|
137 |
|
138 // we have been successful - update the state |
|
139 iLocalFilename = copy_filename; |
|
140 iStatus = DCS_ACTIVE_LOCAL_COPY; |
|
141 return DCE_NONE; |
|
142 } |
|
143 |
|
144 |
|
145 /****************************************************************************************************** |
|
146 * |
|
147 * PUBLIC METHOD: RemoveLocalCopy |
|
148 * |
|
149 *****************************************************************************************************/ |
|
150 TDCFError CDynamicsConfigFile::RemoveLocalCopy( int *aSystemError ) |
|
151 { |
|
152 // check params |
|
153 assert( aSystemError != NULL ); |
|
154 *aSystemError = 0; |
|
155 |
|
156 // check the state |
|
157 if( iStatus != DCS_ACTIVE_LOCAL_COPY ) { |
|
158 return DCE_INVALID_STATE; |
|
159 } |
|
160 |
|
161 // remove the local copy |
|
162 unlink( iLocalFilename.c_str() ); |
|
163 iStatus = DCS_REFERENCE_FILE_SET; |
|
164 return DCE_NONE; |
|
165 } |
|
166 |
|
167 |
|
168 /****************************************************************************************************** |
|
169 * |
|
170 * PUBLIC METHOD: SetSingleOption |
|
171 * |
|
172 *****************************************************************************************************/ |
|
173 TDCFError CDynamicsConfigFile::SetSingleOption( string aLabel, string aValue, int *aSystemError ) |
|
174 { |
|
175 TFUError ferr; |
|
176 int line_numbers[MAXTOKENMATCHES], match_count, insert_line, replace_flag = 1; |
|
177 |
|
178 // check params |
|
179 assert( aSystemError != NULL ); |
|
180 *aSystemError = 0; |
|
181 |
|
182 // check the state |
|
183 if( iStatus != DCS_ACTIVE_LOCAL_COPY ) { |
|
184 return DCE_INVALID_STATE; |
|
185 } |
|
186 |
|
187 // get the list of occurences of the label |
|
188 match_count = MAXTOKENMATCHES; |
|
189 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aLabel.c_str(), line_numbers, &match_count, aSystemError ); |
|
190 if( ferr != FUE_NONE ) { |
|
191 return (TDCFError)ferr; |
|
192 } |
|
193 |
|
194 // make sure there is one or zero occurences |
|
195 if( match_count > 1 ) { |
|
196 return DCE_MULTIPLE_MATCHES; |
|
197 } |
|
198 |
|
199 // set the line to insert at -- if zero occurences then add at the start of the file and DONT REPLACE |
|
200 insert_line = line_numbers[0]; |
|
201 if( match_count == 0 ) { |
|
202 insert_line = 1; |
|
203 replace_flag = 0; |
|
204 } |
|
205 |
|
206 // insert the line |
|
207 ferr = InsertLine( (char*)iLocalFilename.c_str(), insert_line, (char*)aValue.c_str(), aValue.length(), replace_flag, aSystemError ); |
|
208 if( ferr != FUE_NONE ) { |
|
209 return (TDCFError)ferr; |
|
210 } |
|
211 |
|
212 // done |
|
213 return DCE_NONE; |
|
214 } |
|
215 |
|
216 |
|
217 /****************************************************************************************************** |
|
218 * |
|
219 * PUBLIC METHOD: AddListOption |
|
220 * |
|
221 *****************************************************************************************************/ |
|
222 TDCFError CDynamicsConfigFile::AddListOption( string aBlockStartTag, string aBlockEndTag, string aLineItem, int *aSystemError ) |
|
223 { |
|
224 TFUError ferr; |
|
225 int start_block_tag[MAXTOKENMATCHES], end_block_tag[MAXTOKENMATCHES], start_block_count, end_block_count; |
|
226 |
|
227 // check params |
|
228 assert( aSystemError != NULL ); |
|
229 *aSystemError = 0; |
|
230 |
|
231 // check the state |
|
232 if( iStatus != DCS_ACTIVE_LOCAL_COPY ) { |
|
233 return DCE_INVALID_STATE; |
|
234 } |
|
235 |
|
236 // count the number of times the block start label appears in the file -- must 1 here |
|
237 start_block_count = MAXTOKENMATCHES; |
|
238 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aBlockStartTag.c_str(), start_block_tag, &start_block_count, aSystemError ); |
|
239 if( ferr != FUE_NONE ) { |
|
240 return (TDCFError)ferr; |
|
241 } |
|
242 |
|
243 // count the number of times the block end label appears in the file -- must 1 here |
|
244 end_block_count = MAXTOKENMATCHES; |
|
245 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aBlockEndTag.c_str(), end_block_tag, &end_block_count, aSystemError ); |
|
246 if( ferr != FUE_NONE ) { |
|
247 return (TDCFError)ferr; |
|
248 } |
|
249 |
|
250 // make sure there is exactly one of each tag |
|
251 if( start_block_count == 0 ) { |
|
252 return DCE_START_TAG_NOT_FOUND; |
|
253 } |
|
254 if( start_block_count > 1 ) { |
|
255 return DCE_MULTIPLE_START_TAGS_FOUND; |
|
256 } |
|
257 if( end_block_count == 0 ) { |
|
258 return DCE_END_TAG_NOT_FOUND; |
|
259 } |
|
260 if( end_block_count > 1 ) { |
|
261 return DCE_MULTIPLE_END_TAGS_FOUND; |
|
262 } |
|
263 |
|
264 // ok - insert the line before the end tag |
|
265 ferr = InsertLine( (char*)iLocalFilename.c_str(), end_block_tag[0], (char*)aLineItem.c_str(), aLineItem.length(), 0, aSystemError ); |
|
266 if( ferr != FUE_NONE ) { |
|
267 return (TDCFError)ferr; |
|
268 } |
|
269 |
|
270 // done |
|
271 return DCE_NONE; |
|
272 } |
|
273 |
|
274 |
|
275 /****************************************************************************************************** |
|
276 * |
|
277 * PUBLIC METHOD: RemoveListOption |
|
278 * |
|
279 *****************************************************************************************************/ |
|
280 TDCFError CDynamicsConfigFile::RemoveListOption( string aBlockStartTag, string aBlockEndTag, string aFirstToken, int *aSystemError ) |
|
281 { |
|
282 TFUError ferr; |
|
283 int start_block_tag[MAXTOKENMATCHES], end_block_tag[MAXTOKENMATCHES], entries[MAXTOKENMATCHES], start_block_count, end_block_count, entry_count; |
|
284 int i; |
|
285 |
|
286 // check params |
|
287 assert( aSystemError != NULL ); |
|
288 *aSystemError = 0; |
|
289 |
|
290 // check the state |
|
291 if( iStatus != DCS_ACTIVE_LOCAL_COPY ) { |
|
292 return DCE_INVALID_STATE; |
|
293 } |
|
294 |
|
295 // count the number of times the block start label appears in the file -- must 1 here |
|
296 start_block_count = MAXTOKENMATCHES; |
|
297 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aBlockStartTag.c_str(), start_block_tag, &start_block_count, aSystemError ); |
|
298 if( ferr != FUE_NONE ) { |
|
299 return (TDCFError)ferr; |
|
300 } |
|
301 |
|
302 // count the number of times the block end label appears in the file -- must 1 here |
|
303 end_block_count = MAXTOKENMATCHES; |
|
304 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aBlockEndTag.c_str(), end_block_tag, &end_block_count, aSystemError ); |
|
305 if( ferr != FUE_NONE ) { |
|
306 return (TDCFError)ferr; |
|
307 } |
|
308 |
|
309 // make sure there is exactly one of each tag |
|
310 if( start_block_count <= 0 ) { |
|
311 return DCE_START_TAG_NOT_FOUND; |
|
312 } else if( end_block_count <= 0 ) { |
|
313 return DCE_END_TAG_NOT_FOUND; |
|
314 } else if( start_block_count > 1 ) { |
|
315 return DCE_MULTIPLE_START_TAGS_FOUND; |
|
316 } else if( end_block_count > 1 ) { |
|
317 return DCE_MULTIPLE_END_TAGS_FOUND; |
|
318 } |
|
319 assert( (start_block_count == 1) && (end_block_count == 1) ); |
|
320 |
|
321 // count the number of lines matching the token |
|
322 entry_count = MAXTOKENMATCHES; |
|
323 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aFirstToken.c_str(), entries, &entry_count, aSystemError ); |
|
324 if( ferr != FUE_NONE ) { |
|
325 return (TDCFError)ferr; |
|
326 } |
|
327 |
|
328 // now look for the first entry that is between the tags |
|
329 for( i = 0; i < entry_count; i++ ) { |
|
330 if( (entries[i] >= start_block_tag[0]) && (entries[i] <= end_block_tag[0]) ) |
|
331 break; |
|
332 } |
|
333 |
|
334 // if no match was found between the tags then exit |
|
335 if( i == entry_count ) { |
|
336 return DCE_ENTRY_NOT_FOUND; |
|
337 } |
|
338 |
|
339 // remove the line |
|
340 ferr = InsertLine( (char*)iLocalFilename.c_str(), entries[i], NULL, 0, 1, aSystemError ); |
|
341 if( ferr != FUE_NONE ) { |
|
342 return (TDCFError)ferr; |
|
343 } |
|
344 |
|
345 // done |
|
346 return DCE_NONE; |
|
347 } |
|
348 |
|
349 |
|
350 /****************************************************************************************************** |
|
351 * |
|
352 * PUBLIC METHOD: RemoveListOption |
|
353 * |
|
354 *****************************************************************************************************/ |
|
355 TDCFError CDynamicsConfigFile::RemoveSingleOption( string aLabel, int *aSystemError ) |
|
356 { |
|
357 TFUError ferr; |
|
358 int line_numbers[MAXTOKENMATCHES], match_count, insert_line; |
|
359 char nline[MAXLINESIZE]; |
|
360 |
|
361 // check params |
|
362 assert( aSystemError != NULL ); |
|
363 *aSystemError = 0; |
|
364 |
|
365 // check the state |
|
366 if( iStatus != DCS_ACTIVE_LOCAL_COPY ) { |
|
367 return DCE_INVALID_STATE; |
|
368 } |
|
369 |
|
370 // get the list of occurences of the label |
|
371 match_count = MAXTOKENMATCHES; |
|
372 ferr = FindMatchingLines( (char*)iLocalFilename.c_str(), (char*)aLabel.c_str(), line_numbers, &match_count, aSystemError ); |
|
373 if( ferr != FUE_NONE ) { |
|
374 return (TDCFError)ferr; |
|
375 } |
|
376 |
|
377 // make sure there is one or zero occurences |
|
378 if( match_count > 1 ) { |
|
379 return DCE_MULTIPLE_MATCHES; |
|
380 } |
|
381 |
|
382 // if there is zero then there is nothing to set |
|
383 if( match_count == 0 ) { |
|
384 return DCE_NONE; |
|
385 } |
|
386 |
|
387 // otherwise replace the line with the string '# aLabel' |
|
388 assert( match_count == 1 ); |
|
389 insert_line = line_numbers[0]; |
|
390 snprintf( nline, MAXLINESIZE, "# %s", aLabel.c_str() ); |
|
391 |
|
392 // insert the line |
|
393 ferr = InsertLine( (char*)iLocalFilename.c_str(), insert_line, nline, strlen(nline), 1, aSystemError ); |
|
394 if( ferr != FUE_NONE ) { |
|
395 return (TDCFError)ferr; |
|
396 } |
|
397 |
|
398 // done |
|
399 return DCE_NONE; |
|
400 } |
|
401 |
|
402 |
|
403 /****************************************************************************************************** |
|
404 * |
|
405 * PUBLIC METHOD: GetLocalFilename |
|
406 * |
|
407 *****************************************************************************************************/ |
|
408 const char *CDynamicsConfigFile::GetLocalFilename() |
|
409 { |
|
410 return iLocalFilename.c_str(); |
|
411 } |