root/libutil/path.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isabspath
  2. canonpath
  3. realpath
  4. makedirectories
  5. trimpath

   1 /*
   2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2008, 2011
   3  *      Tama Communications Corporation
   4  * #ifdef __DJGPP__
   5  * Contributed by Jason Hood <jadoxa@yahoo.com.au>, 2001.
   6  # #endif
   7  *
   8  * This file is part of GNU GLOBAL.
   9  *
  10  * This program is free software: you can redistribute it and/or modify
  11  * it under the terms of the GNU General Public License as published by
  12  * the Free Software Foundation, either version 3 of the License, or
  13  * (at your option) any later version.
  14  * 
  15  * This program is distributed in the hope that it will be useful,
  16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18  * GNU General Public License for more details.
  19  * 
  20  * You should have received a copy of the GNU General Public License
  21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22  */
  23 
  24 #ifdef HAVE_CONFIG_H
  25 #include <config.h>
  26 #endif
  27 #ifdef HAVE_STRING_H
  28 #include <string.h>
  29 #else
  30 #include <strings.h>
  31 #endif
  32 #include <sys/types.h>
  33 #include <sys/stat.h>
  34 
  35 #ifdef __DJGPP__
  36 #include <fcntl.h>                      /* for _USE_LFN */
  37 #endif
  38 
  39 #include "gparam.h"
  40 #include "path.h"
  41 #include "strbuf.h"
  42 #include "strlimcpy.h"
  43 #include "test.h"
  44 
  45 
  46 /**
  47  * isabspath: whether absolute path or not
  48  *
  49  *      @param[in]      p       path
  50  *      @return         1: absolute, 0: not absolute
  51  */
  52 int
  53 isabspath(const char *p)
  54 {
  55         if (p[0] == '/')
  56                 return 1;
  57 #if defined(_WIN32) || defined(__DJGPP__)
  58         if (p[0] == '\\')
  59                 return 1;
  60         if (isdrivechar(p[0]) && p[1] == ':' && (p[2] == '\\' || p[2] == '/'))
  61                 return 1;
  62 #endif
  63         return 0;
  64 }
  65 
  66 /**
  67  * canonpath: make canonical path name.
  68  *
  69  *      @param[in,out]  path    path
  70  *      @return         path
  71  *
  72  * @attention canonpath() rewrite argument buffer.
  73  */
  74 char *
  75 canonpath(char *path)
  76 {
  77 #ifdef __DJGPP__
  78         char *p;
  79 
  80         if (_USE_LFN) {
  81                 char name[260], sfn[13];
  82                 char *base;
  83 
  84                 /*
  85                  * Ensure we're using a complete long name, not a mixture
  86                  * of long and short.
  87                  */
  88                 _truename(path, path);
  89                 /*
  90                  * _truename will successfully convert the path of a non-
  91                  * existant file, but it's probably still a mixture of long and
  92                  * short components - convert the path separately.
  93                  */
  94                 if (access(path, F_OK) != 0) {
  95                         base = basename(path);
  96                         strcpy(name, base);
  97                         *base = '\0';
  98                         _truename(path, path);
  99                         strcat(path, name);
 100                 }
 101                 /*
 102                  * Convert the case of 8.3 names, as other djgpp functions do.
 103                  */
 104                 if (!_preserve_fncase()) {
 105                         for (p = path+3, base = p-1; *base; p++) {
 106                                 if (*p == '\\' || *p == '\0') {
 107                                         memcpy(name, base+1, p-base-1);
 108                                         name[p-base-1] = '\0';
 109                                         if (!strcmp(_lfn_gen_short_fname(name, sfn), name)) {
 110                                                 while (++base < p)
 111                                                         if (*base >= 'A' && *base <= 'Z')
 112                                                                 *base += 'a' - 'A';
 113                                         } else
 114                                            base = p;
 115                                 }
 116                         }
 117                 }
 118         }
 119         /*
 120          * Lowercase the drive letter and convert to slashes.
 121          */
 122         path[0] = tolower(path[0]);
 123         for (p = path+2; *p; ++p)
 124                 if (*p == '\\')
 125                         *p = '/';
 126 #else
 127 #ifdef _WIN32
 128         char *p, *s;
 129         p = path;
 130         /*
 131          * Change \ to / in a path (for DOS/Windows paths)
 132          */
 133         while ((p = strchr(p, '\\')) != NULL)
 134                 *p = '/';
 135 #ifdef __CYGWIN__
 136         /*
 137          * On NT with CYGWIN, getcwd can return something like
 138          * "//c/tmp", which isn't usable. We change that to "c:/tmp".
 139          */
 140         p = path;
 141         if (p[0] == '/' && p[1] == '/' && isdrivechar(p[2]) && p[3] == '/') {
 142                 s = &p[2];              /* point drive char */
 143                 *p++ = *s++;
 144                 *p++ = ':';
 145                 while (*p++ = *s++)
 146                         ;
 147         }
 148 #endif /* __CYGWIN__ */
 149 #endif /* _WIN32 */
 150 #endif /* __DJGPP__ */
 151         return path;
 152 }
 153 
 154 #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__DJGPP__)
 155 /**
 156  * realpath: get the complete path
 157  */
 158 char *
 159 realpath(const char *in_path, char *out_path)
 160 {
 161 #ifdef __DJGPP__
 162         /*
 163          * I don't use _fixpath or _truename in LFN because neither guarantee
 164          * a complete long name. This is mainly DOS's fault, since the cwd can
 165          * be a mixture of long and short components.
 166          */
 167         if (_USE_LFN) {
 168                 strlimcpy(out_path, in_path, MAXPATHLEN);
 169                 canonpath(out_path);
 170         } else
 171                 _fixpath(in_path, out_path);
 172 #else
 173         _fullpath(out_path, in_path, MAXPATHLEN);
 174         canonpath(out_path);
 175 #endif
 176         return out_path;
 177 }
 178 #endif
 179 
 180 #define SEP '/'
 181 
 182 /**
 183  * makedirectories: make directories on the path like @XREF{mkdir,1} with the @OPTION{-p} option.
 184  *
 185  *      @param[in]      base    base directory
 186  *      @param[in]      rest    path from the base
 187  *      @param[in]      verbose 1: verbose mode, 0: not verbose mode
 188  *      @return         0: success <br>
 189  *                      -1: base directory not found <br>
 190  *                      -2: permission error <br>
 191  *                      -3: cannot make directory
 192  */
 193 int
 194 makedirectories(const char *base, const char *rest, int verbose)
 195 {
 196         STRBUF *sb;
 197         const char *p, *q;
 198 
 199         if (!test("d", base))
 200                 return -1;
 201         if (!test("drw", base))
 202                 return -2;
 203         sb = strbuf_open(0);
 204         strbuf_puts(sb, base);
 205         if (*rest == SEP)
 206                 rest++;
 207         for (q = rest; *q;) {
 208                 p = q;
 209                 while (*q && *q != SEP)
 210                         q++;
 211                 strbuf_putc(sb, SEP);
 212                 strbuf_nputs(sb, p, q - p);
 213                 p = strbuf_value(sb);
 214                 if (!test("d", p)) {
 215                         if (verbose)
 216                                 fprintf(stderr, " Making directory '%s'.\n", p);
 217 #if defined(_WIN32) && !defined(__CYGWIN__)
 218                         if (mkdir(p) < 0) {
 219 #else
 220                         if (mkdir(p, 0775) < 0) {
 221 #endif /* WIN32 */
 222                                 strbuf_close(sb);
 223                                 return -3;
 224                         }
 225                 }
 226                 if (*q == SEP)
 227                         q++;
 228         }
 229         strbuf_close(sb);
 230         return 0;
 231 }
 232 /**
 233  * trimpath: trim path name
 234  */
 235 const char *
 236 trimpath(const char *path)
 237 {
 238         if (*path == '.' && *(path + 1) == '/')
 239                 path += 2;
 240         return path;
 241 }

/* [previous][next][first][last][top][bottom][index][help] */