wfc_util_fctrl.c revision 5fd819dcca2ce41b0c7fa56d010dca6cbc3cc0d0
1/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
26#include "wfc_util_log.h"
27
28/*
29static void wfc_util_printf(char *pSPointer, int length)
30{
31	char *pPrintBuff = NULL;
32
33	if( NULL == pSPointer || 0 >= length ) {
34		wfc_util_log_error("wfc_util_printf : unvalid parameters");
35		return;
36	}
37
38	wfc_util_log_error("wfc_util_printf : lenght is (%d)", length);
39	pPrintBuff = malloc(length+1);
40
41	if( NULL != pPrintBuff ) {
42		memset( pPrintBuff, 0, (length+1) );
43		memcpy(pPrintBuff, pSPointer, length);
44
45		wfc_util_log_error("wfc_util_printf : %s", pPrintBuff);
46
47		free(pPrintBuff);
48	} else {
49		wfc_util_log_error("wfc_util_printf : can not malloc(%d)", (length+1));
50	}
51	return;
52}
53*/
54
55static void wfc_util_finsert_new_string(int fd, char **ppReadedBuff, char *pNewStringValue, char *pEndOfCfg)
56{
57	off_t sz_file;
58	int   sz_backupBuff = 0;
59	char *pReadBuff = NULL, *pBackupBuff = NULL;
60	char *pSPointer = NULL, *pETagPointer = NULL;
61
62	if( 0 == fd || NULL == pNewStringValue || 0 == strlen(pNewStringValue) ) {
63		wfc_util_log_error("wfc_util_finsert_new_string : unvalid parameters");
64		return;
65	}
66
67	if( NULL == ppReadedBuff) {
68		// TODO:
69		return;
70	} else {
71		pReadBuff = *ppReadedBuff;
72	}
73
74	/*
75	 * find END TAG string
76	 */
77	pETagPointer = strstr(pReadBuff, pEndOfCfg);
78	pSPointer = pETagPointer - 1;
79
80	/*
81	 * calcurate file size and size of the tail of file
82	 */
83	sz_file = lseek( fd,  0, SEEK_END );
84	sz_backupBuff = (int)sz_file - (pETagPointer - pReadBuff);
85
86	/*
87	 * prefare the buffer to store the tail of file
88	 */
89	pBackupBuff = malloc(sz_backupBuff);
90
91	if( NULL != pBackupBuff ) {
92		/*
93		 * copy the tail of file.
94		 */
95		memset( pBackupBuff, 0, sz_backupBuff );
96		memcpy( pBackupBuff, pETagPointer, sz_backupBuff );
97
98		/*
99		 * write new string.
100		 */
101		lseek( fd, (int)(pSPointer-pReadBuff), SEEK_SET );
102		write( fd, pNewStringValue, strlen(pNewStringValue));
103
104		/*
105		 * update pETagPointer.
106		 */
107		pETagPointer = pSPointer + strlen(pNewStringValue);
108
109		/*
110		 * write the tail of file.
111		 */
112		lseek( fd, (int)(pETagPointer-pReadBuff), SEEK_SET );
113		write( fd, pBackupBuff, sz_backupBuff );
114
115		ftruncate(fd, sz_file + strlen(pNewStringValue) - 1); /* we use "-1" becasue of "pSPointer = pETagPointer - 1"*/
116
117		free(pBackupBuff);
118
119		/*
120		 * make new *ppReadedBuff
121		 */
122		if( NULL != ppReadedBuff) {
123			// TODO:
124		}
125	} else {
126		wfc_util_log_error("wfc_util_finsert_new_string : can not malloc(%d)", sz_backupBuff);
127	}
128
129	return;
130}
131
132static void wfc_util_fupdate_string(int fd, char **ppReadedBuff,
133                                    char *pETagPointer, char *pSValuePointer, char *pNewValueString)
134{
135	off_t sz_file;
136	int   sz_newReadBuff = 0;
137	char *pReadBuff = NULL, *pNewReadBuff = NULL, *pCurReadBuff = NULL;
138
139	if( 0 == fd ) {
140		wfc_util_log_error("wfc_util_fupdate_string : unvalid parameters");
141		return;
142	}
143
144	if( NULL == ppReadedBuff) {
145		// TODO:
146		return;
147	} else {
148		pReadBuff = *ppReadedBuff;
149	}
150
151	/*
152	 * calcurate file size and new file size
153	 */
154	sz_file  = lseek( fd,  0, SEEK_END );
155	sz_newReadBuff = (int)sz_file - (int)(pETagPointer - pSValuePointer) + strlen(pNewValueString);
156
157	/*
158	 * prefare the buffer to read file
159	 */
160	pNewReadBuff = malloc(sz_newReadBuff);
161
162	if( NULL != pNewReadBuff ) {
163		/*
164		 * copy buffer
165		 */
166		memset( pNewReadBuff, 0, sz_file );
167		pCurReadBuff = pNewReadBuff;
168		memcpy( pNewReadBuff, pReadBuff, (int)(pSValuePointer-pReadBuff) );
169		pCurReadBuff += (int)(pSValuePointer-pReadBuff);
170
171		/*
172		 * copy new value string
173		 */
174		memcpy( pCurReadBuff, pNewValueString, strlen(pNewValueString));
175		pCurReadBuff += strlen(pNewValueString);
176
177		/*
178		 * copy the remained buffer
179		 */
180		memcpy( pCurReadBuff, pETagPointer, ((int)(sz_file) - (int)(pETagPointer - pReadBuff) + 1));
181
182		/*
183		 * write file and update the file size
184		 */
185		lseek( fd,  0, SEEK_SET );
186		write( fd, pNewReadBuff, sz_newReadBuff);
187		ftruncate(fd, sz_newReadBuff);
188
189		free(pNewReadBuff);
190	} else {
191		wfc_util_log_error("wfc_util_fupdate_string : can not malloc(%d)", (int)sz_newReadBuff);
192	}
193
194	return;
195}
196
197/*
198 * wfc_util_fset_buffer
199 *
200 * return : void
201 */
202void wfc_util_fset_buffer(char *pFileName, int positionStart, unsigned char *pNewValue, int newValueLength)
203{
204	int fd;
205	off_t sz_file;
206	char *pReadBuff = NULL;
207
208	fd = open( pFileName, O_RDWR );
209
210	if( fd >= 0 ) {
211		/*
212		 * calcurate file size
213		 */
214		sz_file  = lseek( fd,  0, SEEK_END );
215
216		/*
217		 * prefare the buffer to read file
218		 */
219		pReadBuff = malloc(sz_file + 1);  // null terminated
220
221		if( NULL != pReadBuff ) {
222			/*
223			 * read file
224			 */
225			memset( pReadBuff, 0, sz_file + 1);
226			lseek( fd,  0, SEEK_SET );
227			read( fd, pReadBuff, sz_file );
228
229			if(sz_file >= (positionStart+newValueLength)) {
230				lseek( fd, positionStart, SEEK_SET );
231				write( fd, pNewValue, newValueLength );
232			} else {
233				/*
234				 * insert with new length value buffer
235				 */
236				wfc_util_log_error("wfc_util_fset_buffer : file size(%d) is less than to write position(%d)", (int)sz_file, (positionStart+newValueLength));
237				// TODO:
238			}
239
240			free(pReadBuff);
241		} else {
242			wfc_util_log_error("wfc_util_fset_buffer : can not malloc(%d)", (int)sz_file);
243		}
244
245		if ( -1 == fsync( fd ) ) {
246			wfc_util_log_error("wfc_util_fset_buffer : fail to fsync()");
247		}
248
249		close( fd );
250	} else {
251		wfc_util_log_error("wfc_util_fset_buffer : can not open file");
252	}
253
254	return;
255}
256
257/*
258 * wfc_util_fget_buffer
259 *
260 * return : it will return the length of the stored buffer value if procedure is success
261 *          or will return 0 if not.
262 */
263int wfc_util_fget_buffer(char *pFileName, int positionStart, int lengthToRead, unsigned char *pValueBuff, int buffLength)
264{
265	int result = 0;
266	int fd;
267	off_t sz_file;
268	char *pReadBuff = NULL;
269	char *pSValuePointer = NULL, *pETagPointer = NULL;
270
271	fd = open( pFileName, O_RDONLY );
272
273	if( fd >= 0 ) {
274		/*
275		 * calcurate file size
276		 */
277		sz_file  = lseek( fd,  0, SEEK_END );
278
279		if(sz_file >= (positionStart+lengthToRead)) {
280			/*
281			 * prefare the buffer to read file
282			 */
283			pReadBuff = malloc(sz_file + 1); // null terminated
284
285			if( NULL != pReadBuff ) {
286				/*
287				 * read file
288				 */
289				memset( pReadBuff, 0, sz_file + 1 );
290				lseek( fd,  0, SEEK_SET );
291				read( fd, pReadBuff, sz_file );
292
293				/*
294				 * calculate the start buffer pointer
295				 */
296				pSValuePointer = pReadBuff + positionStart;
297
298				/*
299				 * calculate the end buffer pointer
300				 */
301				pETagPointer = pSValuePointer + lengthToRead;
302
303				/*
304				 * read the string value
305				 */
306				if( buffLength >= (int)(pETagPointer-pSValuePointer) ) {
307					memset( pValueBuff, 0, buffLength );
308					memcpy( pValueBuff, pSValuePointer, (int)(pETagPointer-pSValuePointer) );
309					result = (int)(pETagPointer-pSValuePointer);
310				} else {
311					wfc_util_log_error("wfc_util_fget_buffer : not enough string value buffer(%d)", (int)(pETagPointer-pSValuePointer));
312				}
313
314				free(pReadBuff);
315			} else {
316				wfc_util_log_error("wfc_util_fget_buffer : can not malloc(%d)", (int)sz_file);
317			}
318		} else {
319			wfc_util_log_error("wfc_util_fget_buffer : file size(%d) is less than to read position(%d)", (int)sz_file, (positionStart+lengthToRead));
320		}
321		close( fd );
322	} else {
323		wfc_util_log_error("wfc_util_fget_buffer : can not open file");
324	}
325
326	return result;
327}
328
329/*
330 * wfc_util_fset_string
331 *
332 * The following format string will be added or updated to the file pFileName.
333 * [pSTagString][pNewValueString][pETagString]
334 *
335 * pFileName       : file name and path
336 * pEndOfCfg       : tag string to notify the end of configuration file
337 * pSTagString     : tag string to notify purpose of the value
338 * pETagString     : tag string to notify the end of the value
339 * pNewValueString : string to set for pSTagString
340 *
341 * return : void
342 */
343void wfc_util_fset_string(char *pFileName, char *pEndOfCfg, char *pSTagString, char *pETagString, char *pNewValueString)
344{
345	int fd;
346	off_t sz_file;
347	int   sz_NewValueBuff = 0;
348	char *pReadBuff = NULL, *pNewValueBuff = NULL;
349	char *pSPointer = NULL, *pETagPointer = NULL, *pSValuePointer = NULL;
350
351	fd = open( pFileName, O_RDWR );
352
353	if( fd >= 0 ) {
354		/*
355		 * calcurate file size
356		 */
357		sz_file  = lseek( fd,  0, SEEK_END );
358
359		/*
360		 * prefare the buffer to read file
361		 */
362		if (sz_file > 0)
363			pReadBuff = malloc(sz_file + 1); // null terminated
364
365		if( NULL != pReadBuff ) {
366			/*
367			 * read file
368			 */
369			memset( pReadBuff, 0x00, sz_file + 1);
370			if(lseek(fd, 0, SEEK_SET) != 0) {
371				wfc_util_log_error("lseek failure");
372			}
373			read( fd, pReadBuff, sz_file );
374
375			/* WBT fix, make sure it is terminated with \0 */
376			pReadBuff[sz_file] = '\0';
377
378			/*
379			 * find TAG string
380			 */
381			pSPointer = strstr(pReadBuff, pSTagString);
382
383			if(NULL != pSPointer) {
384				/*
385				 * find END OF LINE string
386				 */
387				pETagPointer = strstr(pSPointer, pETagString);
388
389				if(NULL != pETagPointer) {
390					/*
391					 * write the new string value
392					 */
393					pSValuePointer = pSPointer+strlen(pSTagString);
394					if(strlen(pNewValueString) == (unsigned int)(pETagPointer-pSValuePointer)) {
395						lseek( fd, (int)(pSValuePointer-pReadBuff), SEEK_SET );
396						write( fd, pNewValueString, strlen(pNewValueString));
397					} else {
398						/*
399						 * insert with new length value string
400						 */
401						wfc_util_fupdate_string(fd, &pReadBuff, pETagPointer, pSValuePointer, pNewValueString);
402					}
403				} else {
404					wfc_util_log_error("wfc_util_fset_string : can not find End TAG");
405				}
406			} else {
407				/*
408				 * "\n""[Start TAG][String Value][End TAG]""\n"
409				 */
410				sz_NewValueBuff = strlen(pSTagString) +
411				                  strlen(pNewValueString) +
412				                  strlen(pETagString) +
413				                  2 + 1;
414				pNewValueBuff = malloc( sz_NewValueBuff);
415
416				if( NULL != pNewValueBuff ) {
417					/*
418					 * prefare the new string to insert
419					 */
420					memset( pNewValueBuff, 0, sz_NewValueBuff );
421					sprintf( pNewValueBuff, "%c%s%s%s%c", '\n', pSTagString, pNewValueString, pETagString,'\n' );
422
423					/*
424					 * insert new string to the file
425					 */
426					wfc_util_finsert_new_string(fd, &pReadBuff, pNewValueBuff, pEndOfCfg);
427
428					free( pNewValueBuff );
429				} else {
430					wfc_util_log_error("wfc_util_fset_string : can not malloc(%d)", (int)sz_file);
431				}
432			}
433
434			free(pReadBuff);
435		} else {
436			wfc_util_log_error("wfc_util_fset_string : can not malloc(%d)", (int)sz_file);
437		}
438
439		if ( -1 == fsync( fd ) ) {
440			wfc_util_log_error("wfc_util_fset_string : fail to fsync()");
441		}
442
443		close( fd );
444	} else {
445		wfc_util_log_error("wfc_util_fset_string : can not open file");
446	}
447
448	return;
449}
450
451/*
452 * wfc_util_fget_string
453 *
454 * Read value from the following format string in the file pFileName.
455 * [pSTagString][string value to read][pETagString]
456 *
457 * pFileName        : file name and path
458 * pEndOfCfg        : tag string to notify the end of configuration file
459 * pSTagString      : tag string to notify purpose of the value
460 * pETagString      : tag string to notify the end of the value
461 * pValueStringBuff : string buffer to get string value
462 * stringBuffLength : the length of pValueStringBuff
463 *
464 * return : it will return the length of the stored string value if procedure is success
465 *          or will return 0 if not.
466 */
467int wfc_util_fget_string(char *pFileName, char *pEndOfCfg, char *pSTagString, char *pETagString, char *pValueStringBuff, int stringBuffLength)
468{
469	int result = 0;
470	int fd;
471	off_t sz_file;
472	char *pReadBuff = NULL;
473	char *pSPointer = NULL, *pETagPointer = NULL, *pSValuePointer = NULL;
474
475	/* unused parameter*/
476	pEndOfCfg = pEndOfCfg;
477
478	fd = open( pFileName, O_RDONLY );
479
480	if( fd >= 0 ) {
481		/*
482		 * calcurate file size
483		 */
484		sz_file  = lseek( fd,  0, SEEK_END );
485
486		/*
487		 * prefare the buffer to read file
488		 */
489		if (sz_file > 0)		// skip when value is 0
490			pReadBuff = malloc(sz_file + 1);
491
492		if( NULL != pReadBuff ) {
493			/*
494			 * read file
495			 */
496			memset( pReadBuff, 0, sz_file + 1);
497			if(lseek(fd, 0, SEEK_SET) != 0) {
498				wfc_util_log_error("lseek failure");
499			}
500			read( fd, pReadBuff, sz_file );
501
502			/* WBT fix, make sure it is terminated with \0 */
503			pReadBuff[sz_file] = '\0';
504
505			/*
506			 * find TAG string
507			 */
508			pSPointer = strstr( pReadBuff, pSTagString );
509
510			if( NULL != pSPointer ) {
511				/*
512				 * find END OF LINE string
513				 */
514				pETagPointer = strstr(pSPointer, pETagString);
515
516				if( NULL != pETagPointer ) {
517					/*
518					 * read the string value
519					 */
520					pSValuePointer = pSPointer+strlen(pSTagString);
521					if( stringBuffLength >= (int)(pETagPointer-pSValuePointer) ) {
522						memset( pValueStringBuff, 0, stringBuffLength );
523						memcpy( pValueStringBuff, pSValuePointer, (int)(pETagPointer-pSValuePointer) );
524						result = (int)(pETagPointer-pSValuePointer);
525					} else {
526						wfc_util_log_error("wfc_util_fget_string : not enough string value buffer(%d)", (int)(pETagPointer-pSValuePointer));
527					}
528				} else {
529					wfc_util_log_error("wfc_util_fget_string : can not find End TAG");
530				}
531			} else {
532				wfc_util_log_error("wfc_util_fget_string : can not find Start TAG");
533			}
534			free(pReadBuff);
535		} else {
536			wfc_util_log_error("wfc_util_fget_string : can not malloc(%d)", (int)sz_file);
537		}
538		close( fd );
539	} else {
540		wfc_util_log_error("wfc_util_fget_string : can not open file");
541	}
542
543	return result;
544}
545
546/*
547 * wfc_util_ffile_check
548 *
549 * check whether pDestFName file exist or not
550 *
551 * pFileName   : file name and path
552 * access_mode : R_OK | W_OK | X_OK | F_OK
553 *
554 * return : it will return 0 if the file exist
555 *          or will return -1 if not.
556 */
557int wfc_util_ffile_check(char *pDestFName, int access_mode)
558{
559	struct stat st;
560
561	if (access(pDestFName, access_mode) == 0) {
562		if( stat( pDestFName, &st ) < 0 ) {
563			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
564			return -1;
565		}
566		//check if config file has some data or is it empty due to previous errors
567		if( st.st_size ) {
568			return 0;
569		}
570	} else {
571		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
572	}
573
574	return -1;
575}
576
577/*
578 * wfc_util_ffile_check_copy
579 *
580 * check whether pDestFName file exist if not it will copy from pSourceFName file
581 *
582 * return : it will return 0 if procedure is success
583 *          or will return -1 if not.
584 */
585int wfc_util_ffile_check_copy(char *pDestFName, char *pSourceFName, mode_t mode, uid_t uID, gid_t gID)
586{
587#define WFC_BUFFER_SIZE 2048
588	char buf[WFC_BUFFER_SIZE] = {0}; // Null terminated
589	int srcfd, destfd;
590	int nread;
591	struct stat st;
592
593	if (access(pDestFName, R_OK|W_OK) == 0) {
594		if( stat( pDestFName, &st ) < 0 ) {
595			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
596			return -1;
597		}
598		//check if config file has some data or is it empty due to previous errors
599		if( st.st_size ) {
600			return 0;
601		}
602	//else continue to write the config from default template.
603	} else if (errno != ENOENT) {
604		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
605		return -1;
606	}
607
608	srcfd = open(pSourceFName, O_RDONLY);
609	if (srcfd < 0) {
610		wfc_util_log_error("Cannot open \"%s\": %s", pSourceFName, strerror(errno));
611		return -1;
612	}
613
614	destfd = open(pDestFName, O_CREAT|O_WRONLY, mode);
615	if (destfd < 0) {
616		close(srcfd);
617		wfc_util_log_error("Cannot create \"%s\": %s", pDestFName, strerror(errno));
618		return -1;
619	}
620
621	while ((nread = read(srcfd, buf, WFC_BUFFER_SIZE-1)) != 0) {
622		if (nread < 0) {
623			wfc_util_log_error("Error reading \"%s\": %s", pSourceFName, strerror(errno));
624			close(srcfd);
625			close(destfd);
626			unlink(pDestFName);
627			return -1;
628		}
629		// WBT fix, according to manual, the number of bytes read can't be bigger than read_size. I don't know why WBT complains for this.
630		if (nread < WFC_BUFFER_SIZE)
631			buf[nread] = '\0';
632		else {
633			buf[WFC_BUFFER_SIZE-1] = '\0';
634			nread = WFC_BUFFER_SIZE-1;
635		}
636		write(destfd, buf, nread);
637	}
638
639	close(destfd);
640	close(srcfd);
641
642	/* remove this code because of permission problem when it is accessed from "atd" having system permission. */
643	{
644	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
645	uid_t uid = getuid();
646	gid_t gid = getgid();
647	wfc_util_log_error("Error changing group ownership (%d) of %s to %d: %s", gid, pDestFName, gID, strerror(errno));
648	if (0 == uid) {
649	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
650		if (chown(pDestFName, uID, gID) < 0) {
651			wfc_util_log_error("Error changing group ownership of %s to %d: %s", pDestFName, gID, strerror(errno));
652			unlink(pDestFName);
653			return -1;
654		}
655	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
656	} else {
657		wfc_util_log_error("wfc_util_ffile_check_copy : we can not excute chown[uid = %d, gid = %d]", uid, getgid());
658	}
659	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
660	}
661
662	return 0;
663}
664
665