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 18namespace { 19 20const char* skipWhitespace(const char* p, const char* end) { 21 while (p < end && isspace(*p)) { 22 p++; 23 } 24 return p; 25} 26 27const char* skipNonWhitespace(const char* p, const char* end) { 28 while (p < end && !isspace(*p)) { 29 p++; 30 } 31 return p; 32} 33 34const 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 42size_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 49bool 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