Back to index

nagios-plugins  1.4.16
dirname-lgpl.c
Go to the documentation of this file.
00001 /* dirname.c -- return all but the last element in a file name
00002 
00003    Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software
00004    Foundation, Inc.
00005 
00006    This program is free software: you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 #include <config.h>
00020 
00021 #include "dirname.h"
00022 
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 /* Return the length of the prefix of FILE that will be used by
00027    dir_name.  If FILE is in the working directory, this returns zero
00028    even though `dir_name (FILE)' will return ".".  Works properly even
00029    if there are trailing slashes (by effectively ignoring them).  */
00030 
00031 size_t
00032 dir_len (char const *file)
00033 {
00034   size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
00035   size_t length;
00036 
00037   /* Advance prefix_length beyond important leading slashes.  */
00038   prefix_length += (prefix_length != 0
00039                     ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
00040                        && ISSLASH (file[prefix_length]))
00041                     : (ISSLASH (file[0])
00042                        ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
00043                            && ISSLASH (file[1]) && ! ISSLASH (file[2])
00044                            ? 2 : 1))
00045                        : 0));
00046 
00047   /* Strip the basename and any redundant slashes before it.  */
00048   for (length = last_component (file) - file;
00049        prefix_length < length; length--)
00050     if (! ISSLASH (file[length - 1]))
00051       break;
00052   return length;
00053 }
00054 
00055 
00056 /* In general, we can't use the builtin `dirname' function if available,
00057    since it has different meanings in different environments.
00058    In some environments the builtin `dirname' modifies its argument.
00059 
00060    Return the leading directories part of FILE, allocated with malloc.
00061    Works properly even if there are trailing slashes (by effectively
00062    ignoring them).  Return NULL on failure.
00063 
00064    If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
00065    lstat (base_name (FILE)); } will access the same file.  Likewise,
00066    if the sequence { chdir (dir_name (FILE));
00067    rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
00068    to "foo" in the same directory FILE was in.  */
00069 
00070 char *
00071 mdir_name (char const *file)
00072 {
00073   size_t length = dir_len (file);
00074   bool append_dot = (length == 0
00075                      || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
00076                          && length == FILE_SYSTEM_PREFIX_LEN (file)
00077                          && file[2] != '\0' && ! ISSLASH (file[2])));
00078   char *dir = malloc (length + append_dot + 1);
00079   if (!dir)
00080     return NULL;
00081   memcpy (dir, file, length);
00082   if (append_dot)
00083     dir[length++] = '.';
00084   dir[length] = '\0';
00085   return dir;
00086 }