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 /*
29 static 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 
wfc_util_finsert_new_string(int fd,char ** ppReadedBuff,char * pNewStringValue,char * pEndOfCfg)55 static 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 
wfc_util_fupdate_string(int fd,char ** ppReadedBuff,char * pETagPointer,char * pSValuePointer,char * pNewValueString)132 static 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  */
wfc_util_fset_buffer(char * pFileName,int positionStart,unsigned char * pNewValue,int newValueLength)202 void 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  */
wfc_util_fget_buffer(char * pFileName,int positionStart,int lengthToRead,unsigned char * pValueBuff,int buffLength)263 int 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  */
wfc_util_fset_string(char * pFileName,char * pEndOfCfg,char * pSTagString,char * pETagString,char * pNewValueString)343 void 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  */
wfc_util_fget_string(char * pFileName,char * pEndOfCfg,char * pSTagString,char * pETagString,char * pValueStringBuff,int stringBuffLength)467 int wfc_util_fget_string(char *pFileName, char *pEndOfCfg __attribute__((unused)), char *pSTagString,
468 			 char *pETagString, char *pValueStringBuff, int stringBuffLength)
469 {
470 	int result = 0;
471 	int fd;
472 	off_t sz_file;
473 	char *pReadBuff = NULL;
474 	char *pSPointer = NULL, *pETagPointer = NULL, *pSValuePointer = NULL;
475 
476 	fd = open( pFileName, O_RDONLY );
477 
478 	if( fd >= 0 ) {
479 		/*
480 		 * calcurate file size
481 		 */
482 		sz_file  = lseek( fd,  0, SEEK_END );
483 
484 		/*
485 		 * prefare the buffer to read file
486 		 */
487 		if (sz_file > 0)		// skip when value is 0
488 			pReadBuff = malloc(sz_file + 1);
489 
490 		if( NULL != pReadBuff ) {
491 			/*
492 			 * read file
493 			 */
494 			memset( pReadBuff, 0, sz_file + 1);
495 			if(lseek(fd, 0, SEEK_SET) != 0) {
496 				wfc_util_log_error("lseek failure");
497 			}
498 			read( fd, pReadBuff, sz_file );
499 
500 			/* WBT fix, make sure it is terminated with \0 */
501 			pReadBuff[sz_file] = '\0';
502 
503 			/*
504 			 * find TAG string
505 			 */
506 			pSPointer = strstr( pReadBuff, pSTagString );
507 
508 			if( NULL != pSPointer ) {
509 				/*
510 				 * find END OF LINE string
511 				 */
512 				pETagPointer = strstr(pSPointer, pETagString);
513 
514 				if( NULL != pETagPointer ) {
515 					/*
516 					 * read the string value
517 					 */
518 					pSValuePointer = pSPointer+strlen(pSTagString);
519 					if( stringBuffLength >= (int)(pETagPointer-pSValuePointer) ) {
520 						memset( pValueStringBuff, 0, stringBuffLength );
521 						memcpy( pValueStringBuff, pSValuePointer, (int)(pETagPointer-pSValuePointer) );
522 						result = (int)(pETagPointer-pSValuePointer);
523 					} else {
524 						wfc_util_log_error("wfc_util_fget_string : not enough string value buffer(%d)", (int)(pETagPointer-pSValuePointer));
525 					}
526 				} else {
527 					wfc_util_log_error("wfc_util_fget_string : can not find End TAG");
528 				}
529 			} else {
530 				wfc_util_log_error("wfc_util_fget_string : can not find Start TAG");
531 			}
532 			free(pReadBuff);
533 		} else {
534 			wfc_util_log_error("wfc_util_fget_string : can not malloc(%d)", (int)sz_file);
535 		}
536 		close( fd );
537 	} else {
538 		wfc_util_log_error("wfc_util_fget_string : can not open file");
539 	}
540 
541 	return result;
542 }
543 
544 /*
545  * wfc_util_ffile_check
546  *
547  * check whether pDestFName file exist or not
548  *
549  * pFileName   : file name and path
550  * access_mode : R_OK | W_OK | X_OK | F_OK
551  *
552  * return : it will return 0 if the file exist
553  *          or will return -1 if not.
554  */
wfc_util_ffile_check(char * pDestFName,int access_mode)555 int wfc_util_ffile_check(char *pDestFName, int access_mode)
556 {
557 	struct stat st;
558 
559 	if (access(pDestFName, access_mode) == 0) {
560 		if( stat( pDestFName, &st ) < 0 ) {
561 			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
562 			return -1;
563 		}
564 		//check if config file has some data or is it empty due to previous errors
565 		if( st.st_size ) {
566 			return 0;
567 		}
568 	} else {
569 		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
570 	}
571 
572 	return -1;
573 }
574 
575 /*
576  * wfc_util_ffile_check_copy
577  *
578  * check whether pDestFName file exist if not it will copy from pSourceFName file
579  *
580  * return : it will return 0 if procedure is success
581  *          or will return -1 if not.
582  */
wfc_util_ffile_check_copy(char * pDestFName,char * pSourceFName,mode_t mode,uid_t uID,gid_t gID)583 int wfc_util_ffile_check_copy(char *pDestFName, char *pSourceFName, mode_t mode, uid_t uID, gid_t gID)
584 {
585 #define WFC_BUFFER_SIZE 2048
586 	char buf[WFC_BUFFER_SIZE] = {0}; // Null terminated
587 	int srcfd, destfd;
588 	int nread;
589 	struct stat st;
590 
591 	if (access(pDestFName, R_OK|W_OK) == 0) {
592 		if( stat( pDestFName, &st ) < 0 ) {
593 			wfc_util_log_error("Cannot stat the file \"%s\": %s", pDestFName, strerror(errno));
594 			return -1;
595 		}
596 		//check if config file has some data or is it empty due to previous errors
597 		if( st.st_size ) {
598 			return 0;
599 		}
600 	//else continue to write the config from default template.
601 	} else if (errno != ENOENT) {
602 		wfc_util_log_error("Cannot access \"%s\": %s", pDestFName, strerror(errno));
603 		return -1;
604 	}
605 
606 	srcfd = open(pSourceFName, O_RDONLY);
607 	if (srcfd < 0) {
608 		wfc_util_log_error("Cannot open \"%s\": %s", pSourceFName, strerror(errno));
609 		return -1;
610 	}
611 
612 	destfd = open(pDestFName, O_CREAT|O_WRONLY, mode);
613 	if (destfd < 0) {
614 		close(srcfd);
615 		wfc_util_log_error("Cannot create \"%s\": %s", pDestFName, strerror(errno));
616 		return -1;
617 	}
618 
619 	while ((nread = read(srcfd, buf, WFC_BUFFER_SIZE-1)) != 0) {
620 		if (nread < 0) {
621 			wfc_util_log_error("Error reading \"%s\": %s", pSourceFName, strerror(errno));
622 			close(srcfd);
623 			close(destfd);
624 			unlink(pDestFName);
625 			return -1;
626 		}
627 		// 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.
628 		if (nread < WFC_BUFFER_SIZE)
629 			buf[nread] = '\0';
630 		else {
631 			buf[WFC_BUFFER_SIZE-1] = '\0';
632 			nread = WFC_BUFFER_SIZE-1;
633 		}
634 		write(destfd, buf, nread);
635 	}
636 
637 	close(destfd);
638 	close(srcfd);
639 
640 	/* remove this code because of permission problem when it is accessed from "atd" having system permission. */
641 	{
642 	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
643 	uid_t uid = getuid();
644 	gid_t gid = getgid();
645 	wfc_util_log_error("Error changing group ownership (%d) of %s to %d: %s", gid, pDestFName, gID, strerror(errno));
646 	if (0 == uid) {
647 	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
648 		if (chown(pDestFName, uID, gID) < 0) {
649 			wfc_util_log_error("Error changing group ownership of %s to %d: %s", pDestFName, gID, strerror(errno));
650 			unlink(pDestFName);
651 			return -1;
652 		}
653 	#ifndef CONFIG_LGE_WLAN_WIFI_PATCH
654 	} else {
655 		wfc_util_log_error("wfc_util_ffile_check_copy : we can not excute chown[uid = %d, gid = %d]", uid, getgid());
656 	}
657 	#endif /* CONFIG_LGE_WLAN_WIFI_PATCH */
658 	}
659 
660 	return 0;
661 }
662 
663