Home | History | Annotate | Download | only in filesystems
      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