1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h>
18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdlib.h>
19f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h>
20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <string.h>
213578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <sys/stat.h>
223578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <sys/types.h>
233578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
243578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <fcntl.h>
253578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <dirent.h>
26f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "cutils/log.h"
30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "CommandListener.h"
33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "NetlinkManager.h"
34ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
3529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int process_config(VolumeManager *vm);
383578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void coldboot(const char *path);
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint main() {
41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeManager *vm;
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    CommandListener *cl;
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    NetlinkManager *nm;
45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
4697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGI("Vold 2.1 (the revenge) firing up");
47a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
48a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mkdir("/dev/block/vold", 0755);
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    /* Create our singleton managers */
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!(vm = VolumeManager::Instance())) {
5297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to create VolumeManager");
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    };
55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!(nm = NetlinkManager::Instance())) {
5797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to create NetlinkManager");
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    };
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
61a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    cl = new CommandListener();
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    vm->setBroadcaster((SocketListener *) cl);
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    nm->setBroadcaster((SocketListener *) cl);
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (vm->start()) {
6797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start VolumeManager (%s)", strerror(errno));
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (process_config(vm)) {
7297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
74f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
75f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (nm->start()) {
7697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
77f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
78f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
79f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
803578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    coldboot("/sys/block");
810cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat//    coldboot("/sys/class/switch");
823578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
83f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    /*
84f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat     * Now that we're up, we can respond to commands
85f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat     */
86f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (cl->startListener()) {
8797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start CommandListener (%s)", strerror(errno));
88f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
89f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
90f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
91f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    // Eventually we'll become the monitoring thread
92f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    while(1) {
93f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sleep(1000);
94f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
95f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
9697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGI("Vold exiting");
97f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    exit(0);
98f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
99f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
1003578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void do_coldboot(DIR *d, int lvl)
1013578c41ef138cb3edf38bb488cb9864921f55c79San Mehat{
1023578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    struct dirent *de;
1033578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    int dfd, fd;
1043578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1053578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    dfd = dirfd(d);
1063578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1073578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    fd = openat(dfd, "uevent", O_WRONLY);
1083578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    if(fd >= 0) {
1093578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        write(fd, "add\n", 4);
1103578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        close(fd);
1113578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1123578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1133578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    while((de = readdir(d))) {
1143578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        DIR *d2;
1153578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1163578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if (de->d_name[0] == '.')
1173578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1183578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1193578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if (de->d_type != DT_DIR && lvl > 0)
1203578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1213578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1223578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
1233578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if(fd < 0)
1243578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1253578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1263578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        d2 = fdopendir(fd);
1273578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if(d2 == 0)
1283578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            close(fd);
1293578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        else {
1303578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            do_coldboot(d2, lvl + 1);
1313578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            closedir(d2);
1323578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        }
1333578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1343578c41ef138cb3edf38bb488cb9864921f55c79San Mehat}
1353578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1363578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void coldboot(const char *path)
1373578c41ef138cb3edf38bb488cb9864921f55c79San Mehat{
1383578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    DIR *d = opendir(path);
1393578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    if(d) {
1403578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        do_coldboot(d, 0);
1413578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        closedir(d);
1423578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1433578c41ef138cb3edf38bb488cb9864921f55c79San Mehat}
1443578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
14529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallstatic int parse_mount_flags(char *mount_flags)
14629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall{
14729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char *save_ptr;
14829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int flags = 0;
14929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
15029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (strcasestr(mount_flags, "encryptable")) {
15129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        flags |= VOL_ENCRYPTABLE;
15229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
15329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
15429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (strcasestr(mount_flags, "nonremovable")) {
15529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        flags |= VOL_NONREMOVABLE;
15629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
15729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
15829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return flags;
15929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
16029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
161f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int process_config(VolumeManager *vm) {
162f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    FILE *fp;
163f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    int n = 0;
164f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    char line[255];
165f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
166f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!(fp = fopen("/etc/vold.fstab", "r"))) {
167f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        return -1;
168f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
169f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
170f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    while(fgets(line, sizeof(line), fp)) {
17174ca25a716a060b4f676277262d112b569c5fbd2Jinho You        const char *delim = " \t";
17274ca25a716a060b4f676277262d112b569c5fbd2Jinho You        char *save_ptr;
17329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        char *type, *label, *mount_point, *mount_flags, *sysfs_path;
17429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        int flags;
175f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
176f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        n++;
177f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        line[strlen(line)-1] = '\0';
178f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
179f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        if (line[0] == '#' || line[0] == '\0')
180f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            continue;
181f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
18274ca25a716a060b4f676277262d112b569c5fbd2Jinho You        if (!(type = strtok_r(line, delim, &save_ptr))) {
18397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Error parsing type");
184f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            goto out_syntax;
185f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
18674ca25a716a060b4f676277262d112b569c5fbd2Jinho You        if (!(label = strtok_r(NULL, delim, &save_ptr))) {
18797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Error parsing label");
188f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            goto out_syntax;
189f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
19074ca25a716a060b4f676277262d112b569c5fbd2Jinho You        if (!(mount_point = strtok_r(NULL, delim, &save_ptr))) {
19197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Error parsing mount point");
192f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            goto out_syntax;
193f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
194f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
195f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        if (!strcmp(type, "dev_mount")) {
196ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat            DirectVolume *dv = NULL;
19774ca25a716a060b4f676277262d112b569c5fbd2Jinho You            char *part;
198f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
19974ca25a716a060b4f676277262d112b569c5fbd2Jinho You            if (!(part = strtok_r(NULL, delim, &save_ptr))) {
20097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Error parsing partition");
201f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                goto out_syntax;
202f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            }
203f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            if (strcmp(part, "auto") && atoi(part) == 0) {
20497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Partition must either be 'auto' or 1 based index instead of '%s'", part);
205f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                goto out_syntax;
206f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            }
207f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(part, "auto")) {
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                dv = new DirectVolume(vm, label, mount_point, -1);
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            } else {
211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                dv = new DirectVolume(vm, label, mount_point, atoi(part));
212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            }
213f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
21429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            while ((sysfs_path = strtok_r(NULL, delim, &save_ptr))) {
21529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                if (*sysfs_path != '/') {
21629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                    /* If the first character is not a '/', it must be flags */
21729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                    break;
21829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                }
219f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                if (dv->addPath(sysfs_path)) {
22097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                    SLOGE("Failed to add devpath %s to volume %s", sysfs_path,
221f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                         label);
222f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                    goto out_fail;
223f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                }
224f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            }
22529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
22629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            /* If sysfs_path is non-null at this point, then it contains
22729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall             * the optional flags for this volume
22829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall             */
22929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            if (sysfs_path)
23029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                flags = parse_mount_flags(sysfs_path);
23129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            else
23229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                flags = 0;
23329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            dv->setFlags(flags);
23429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
235f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            vm->addVolume(dv);
236f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        } else if (!strcmp(type, "map_mount")) {
237f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        } else {
23897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Unknown type '%s'", type);
239f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            goto out_syntax;
240f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
241f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
242f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
243f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    fclose(fp);
244f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
245f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
246f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatout_syntax:
24797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGE("Syntax error on config line %d", n);
248f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    errno = -EINVAL;
249f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatout_fail:
250f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    fclose(fp);
251f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return -1;
252f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
253