/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */ /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */ /* Copyright (C) 2014 Stony Brook University This file is part of Graphene Library OS. Graphene Library OS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Graphene Library OS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* * path.c * * This file contains functions to read app config (manifest) file and create * a tree to lookup / access config values. */ #include #include int get_norm_path (const char * path, char * buf, int offset, int size) { int head = offset; char c, c1; const char * p = path; while (head) { /* find the real head, not interrupted by dot-dot */ if (head > 1 && buf[head - 1] == '.' && buf[head - 2] == '.') break; head--; } for (c = '/' ; c ; c = c1, p++) { c1 = *p; if (c == '/') { /* find a slash, or the beginning of the path */ if (c1 == 0) /* no more path */ break; if (c1 == '/') /* consequential slashes */ continue; if (c1 == '.') { /* find a dot, can be dot-dot or a file */ c1 = *(++p); if (c1 == 0) /* no more path */ break; if (c1 == '/') /* a dot, skip it */ continue; if (c1 == '.') { /* must be dot-dot */ c1 = *(++p); if (c1 != 0 && c1 != '/') { /* Paths can start with a dot * dot: ..xyz is ok */ if (offset >= size - 2) return -PAL_ERROR_TOOLONG; buf[offset++] = '.'; buf[offset++] = '.'; continue; } if (offset > head) { /* remove the last token */ while (offset > head && buf[--offset] != '/'); } else { if (offset) { /* add a slash */ if (offset >= size - 1) return -PAL_ERROR_TOOLONG; buf[offset++] = '/'; } /* add a dot-dot */ if (offset >= size - 2) return -PAL_ERROR_TOOLONG; buf[offset++] = '.'; buf[offset++] = '.'; head = offset; } } else { /* it's a file */ if (offset) { /* add a slash */ if (offset >= size - 1) return -PAL_ERROR_TOOLONG; buf[offset++] = '/'; } if (offset >= size - 1) return -PAL_ERROR_TOOLONG; buf[offset++] = '.'; } continue; } } if (offset || c != '/' || *path == '/') { if (offset >= size - 1) return -PAL_ERROR_TOOLONG; buf[offset++] = c; } } buf[offset] = 0; return offset; } int get_base_name (const char * path, char * buf, int size) { const char * p = path; for (; *p ; p++) { if (*p == '/') continue; if (*p == '.') { if (*(p + 1) == '/' || !*(p + 1)) { p++; continue; } if (*(p + 1) == '.') { if (*(p + 2) == '/' || !*(p + 2)) { p += 2; continue; } } } const char * e = p + 1; for (; *e && *e != '/' ; e++); if (*e) { p = e - 1; continue; } if (e - p > size - 1) return -PAL_ERROR_TOOLONG; int offset = 0; for (; p < e ; p++, offset++) buf[offset] = *p; buf[offset] = 0; return offset; } return 0; }