xref: /dragonfly/contrib/cvs-1.12/lib/dirname.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /* dirname.c -- return all but the last element in a file name
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino    Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005 Free Software
4*86d7f5d3SJohn Marino    Foundation, Inc.
5*86d7f5d3SJohn Marino 
6*86d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
7*86d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
8*86d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
9*86d7f5d3SJohn Marino    any later version.
10*86d7f5d3SJohn Marino 
11*86d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
12*86d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*86d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*86d7f5d3SJohn Marino    GNU General Public License for more details.
15*86d7f5d3SJohn Marino 
16*86d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
17*86d7f5d3SJohn Marino    along with this program; if not, write to the Free Software Foundation,
18*86d7f5d3SJohn Marino    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19*86d7f5d3SJohn Marino 
20*86d7f5d3SJohn Marino #ifdef HAVE_CONFIG_H
21*86d7f5d3SJohn Marino # include <config.h>
22*86d7f5d3SJohn Marino #endif
23*86d7f5d3SJohn Marino 
24*86d7f5d3SJohn Marino #include "dirname.h"
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino #include <string.h>
27*86d7f5d3SJohn Marino #include "xalloc.h"
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino /* Return the length of `dirname (FILE)', or zero if FILE is
30*86d7f5d3SJohn Marino    in the working directory.  Works properly even if
31*86d7f5d3SJohn Marino    there are trailing slashes (by effectively ignoring them).  */
32*86d7f5d3SJohn Marino size_t
dir_len(char const * file)33*86d7f5d3SJohn Marino dir_len (char const *file)
34*86d7f5d3SJohn Marino {
35*86d7f5d3SJohn Marino   size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
36*86d7f5d3SJohn Marino   size_t length;
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino   /* Strip the basename and any redundant slashes before it.  */
39*86d7f5d3SJohn Marino   for (length = base_name (file) - file;  prefix_length < length;  length--)
40*86d7f5d3SJohn Marino     if (! ISSLASH (file[length - 1]))
41*86d7f5d3SJohn Marino       return length;
42*86d7f5d3SJohn Marino 
43*86d7f5d3SJohn Marino   /* But don't strip the only slash from "/".  */
44*86d7f5d3SJohn Marino   return prefix_length + ISSLASH (file[prefix_length]);
45*86d7f5d3SJohn Marino }
46*86d7f5d3SJohn Marino 
47*86d7f5d3SJohn Marino /* Return the leading directories part of FILE,
48*86d7f5d3SJohn Marino    allocated with xmalloc.
49*86d7f5d3SJohn Marino    Works properly even if there are trailing slashes
50*86d7f5d3SJohn Marino    (by effectively ignoring them).  */
51*86d7f5d3SJohn Marino 
52*86d7f5d3SJohn Marino char *
dir_name(char const * file)53*86d7f5d3SJohn Marino dir_name (char const *file)
54*86d7f5d3SJohn Marino {
55*86d7f5d3SJohn Marino   size_t length = dir_len (file);
56*86d7f5d3SJohn Marino   bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (file));
57*86d7f5d3SJohn Marino   char *dir = xmalloc (length + append_dot + 1);
58*86d7f5d3SJohn Marino   memcpy (dir, file, length);
59*86d7f5d3SJohn Marino   if (append_dot)
60*86d7f5d3SJohn Marino     dir[length++] = '.';
61*86d7f5d3SJohn Marino   dir[length] = 0;
62*86d7f5d3SJohn Marino   return dir;
63*86d7f5d3SJohn Marino }
64*86d7f5d3SJohn Marino 
65*86d7f5d3SJohn Marino #ifdef TEST_DIRNAME
66*86d7f5d3SJohn Marino /*
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino Run the test like this (expect no output):
69*86d7f5d3SJohn Marino   gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
70*86d7f5d3SJohn Marino      basename.c dirname.c xmalloc.c error.c
71*86d7f5d3SJohn Marino   sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
72*86d7f5d3SJohn Marino 
73*86d7f5d3SJohn Marino If it's been built on a DOS or Windows platforms, run another test like
74*86d7f5d3SJohn Marino this (again, expect no output):
75*86d7f5d3SJohn Marino   sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
76*86d7f5d3SJohn Marino 
77*86d7f5d3SJohn Marino BEGIN-DATA
78*86d7f5d3SJohn Marino foo//// .
79*86d7f5d3SJohn Marino bar/foo//// bar
80*86d7f5d3SJohn Marino foo/ .
81*86d7f5d3SJohn Marino / /
82*86d7f5d3SJohn Marino . .
83*86d7f5d3SJohn Marino a .
84*86d7f5d3SJohn Marino END-DATA
85*86d7f5d3SJohn Marino 
86*86d7f5d3SJohn Marino BEGIN-DOS-DATA
87*86d7f5d3SJohn Marino c:///// c:/
88*86d7f5d3SJohn Marino c:/ c:/
89*86d7f5d3SJohn Marino c:/. c:/
90*86d7f5d3SJohn Marino c:foo c:.
91*86d7f5d3SJohn Marino c:foo/bar c:foo
92*86d7f5d3SJohn Marino END-DOS-DATA
93*86d7f5d3SJohn Marino 
94*86d7f5d3SJohn Marino */
95*86d7f5d3SJohn Marino 
96*86d7f5d3SJohn Marino # define MAX_BUFF_LEN 1024
97*86d7f5d3SJohn Marino # include <stdio.h>
98*86d7f5d3SJohn Marino 
99*86d7f5d3SJohn Marino char *program_name;
100*86d7f5d3SJohn Marino 
101*86d7f5d3SJohn Marino int
main(int argc,char * argv[])102*86d7f5d3SJohn Marino main (int argc, char *argv[])
103*86d7f5d3SJohn Marino {
104*86d7f5d3SJohn Marino   char buff[MAX_BUFF_LEN + 1];
105*86d7f5d3SJohn Marino 
106*86d7f5d3SJohn Marino   program_name = argv[0];
107*86d7f5d3SJohn Marino 
108*86d7f5d3SJohn Marino   buff[MAX_BUFF_LEN] = 0;
109*86d7f5d3SJohn Marino   while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
110*86d7f5d3SJohn Marino     {
111*86d7f5d3SJohn Marino       char file[MAX_BUFF_LEN];
112*86d7f5d3SJohn Marino       char expected_result[MAX_BUFF_LEN];
113*86d7f5d3SJohn Marino       char const *result;
114*86d7f5d3SJohn Marino       sscanf (buff, "%s %s", file, expected_result);
115*86d7f5d3SJohn Marino       result = dir_name (file);
116*86d7f5d3SJohn Marino       if (strcmp (result, expected_result))
117*86d7f5d3SJohn Marino 	printf ("%s: got %s, expected %s\n", file, result, expected_result);
118*86d7f5d3SJohn Marino     }
119*86d7f5d3SJohn Marino   return 0;
120*86d7f5d3SJohn Marino }
121*86d7f5d3SJohn Marino #endif
122