1 // Copyright 2014 The Android Open Source Project 2 // 3 // This software is licensed under the terms of the GNU General Public 4 // License version 2, as published by the Free Software Foundation, and 5 // may be copied, distributed, and modified under those terms. 6 // 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License for more details. 11 12 #include "android/filesystems/fstab_parser.h" 13 14 #include <ctype.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 namespace { 19 20 const char* skipWhitespace(const char* p, const char* end) { 21 while (p < end && isspace(*p)) { 22 p++; 23 } 24 return p; 25 } 26 27 const char* skipNonWhitespace(const char* p, const char* end) { 28 while (p < end && !isspace(*p)) { 29 p++; 30 } 31 return p; 32 } 33 34 const char* skipExpectedToken(const char* p, const char* end) { 35 p = skipWhitespace(p, end); 36 if (p == end) { 37 return NULL; 38 } 39 return skipNonWhitespace(p, end); 40 } 41 42 size_t getTokenLen(const char* p, const char* end) { 43 const char* q = skipNonWhitespace(p, end); 44 return (size_t)(q - p); 45 } 46 47 } // namespace 48 49 bool android_parseFstabPartitionFormat(const char* fstabData, 50 size_t fstabSize, 51 const char* partitionName, 52 char** out) { 53 const char* p = fstabData; 54 const char* end = p + fstabSize; 55 56 size_t partitionNameLen = strlen(partitionName); 57 58 while (p < end) { 59 // Find end of current line, and start of next one. 60 const char* line = p; 61 const char* line_end = ::strchr(p, '\n'); 62 if (!line_end) { 63 line_end = end; 64 p = end; 65 } else { 66 p = line_end + 1; 67 } 68 69 // Skip empty or comment lines. 70 line = skipWhitespace(line, line_end); 71 if (line == line_end || line[0] == '#') { 72 continue; 73 } 74 75 // expected format: <device><ws><partition><ws><format><ws><options> 76 77 // skip over device name. 78 line = skipExpectedToken(line, line_end); 79 if (!line) { 80 continue; 81 } 82 83 line = skipWhitespace(line, line_end); 84 size_t tokenLen = getTokenLen(line, line_end); 85 if (tokenLen != partitionNameLen || 86 memcmp(line, partitionName, tokenLen) != 0) { 87 // Not the right partition. 88 continue; 89 } 90 91 line = skipWhitespace(line + tokenLen, line_end); 92 size_t formatLen = getTokenLen(line, line_end); 93 if (formatLen == 0) { 94 // Malformed data. 95 return false; 96 } 97 98 *out = static_cast<char*>(malloc(formatLen + 1U)); 99 memcpy(*out, line, formatLen); 100 (*out)[formatLen] = '\0'; 101 return true; 102 } 103 return false; 104 } 105