« May 2008
SunMonTueWedThuFriSat
    
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
       
Today
XML

Tom Haynes

loghyr.com
excfb.com

Blogs to Gander At

Navigation

Editing

AllMarks

Referers

Today's Page Hits: 1246

Powered by Roller Weblogger.

statcounter.com

clustrmaps.com

Locations of visitors to this page

technorati.com

www.alesti.org

Add to Alesti RSS Reader

South Park as I was 10 years ago

South Park Fantasy

South Park today

South Park Reality

I have more hair and it isn't so grey. :->

10 years ago, really

Toon Tom

Today, literally

Tom Today

Site notes

This page validates as XHTML 1.0, and will look much better in a browser that supports web standards, but it is accessible to any browser or Internet device. It was created using techniques detailed at glish.com/css/.

« Subnet evaluation is... | Main | Getting a webrev... »
20080122 Tuesday January 22, 2008
Exploring pulling apart a path

Given a directory path entry to a file, I want to find:

I can probably find a standard function to do this, but where is the fun in that?

You might notice I am being vague with the extension and basename, I'm giving the definition we know from common usage, not a precise one. We'll see why in a bit. And I am assuming we are passing in a file and not a directroy.

I've got the code sitting in the policy prototype, but I pulled it out to focus on and to do some fun unit testing. So, here is the code:

#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef struct {
	char	*ext;
	char	*path;
	char	*base;
	char	*file;
} policyAttributes_t;

int
main (int argc, char *argv[])
{
	policyAttributes_t	pat;

	int	rc = 0;

	char	*junk;
	char	*s;

	/*
	 * Do some initialization.
	 */
	memset(&pat, '\0', sizeof(pat));

	pat.path = strdup(argv[1]);
	if (pat.path == NULL) {
...
	}

	/*
	 * Now we need the file.
	 */
	s = strrchr(argv[1], '/');
	if (s) {
		junk = strdup(s+1);
		if (junk == NULL) {
...
		}

		pat.file = strdup(junk);
		if (pat.file == NULL) {
...
		}

		s = strrchr(junk, '.');
		if (s) {
			pat.ext = strdup(s+1);
			if (junk == NULL) {
...
			}

			*s = '\0';
		}

		pat.base = junk;
	}

cleanup:

	if (pat.path) {
		printf("path = <%s>\n", pat.path);
		free(pat.path);
	}

	if (pat.ext) {
		printf("ext  = <%s>\n", pat.ext);
		free(pat.ext);
	}

	if (pat.base) {
		printf("base = <%s>\n", pat.base);
		free(pat.base);
	}

	if (pat.file) {
		printf("file = <%s>\n", pat.file);
		free(pat.file);
	}

	return (rc);
}

You can see I pulled it out of the other code - I preserved the pat variable. Anyway, I was mostly worried about the pointer manipulation, but I shouldn't have:

% ./a.out /foo/bar.c
path = </foo/bar.c>
ext  = <c>
base = <bar>
file = <bar.c>
% ./a.out /foo/grabba/yabba/bar.c
path = </foo/grabba/yabba/bar.c>
ext  = <c>
base = <bar>
file = <bar.c>
% ./a.out /foo/grabba/yabba/bar
path = </foo/grabba/yabba/bar>
base = <bar>
file = <bar>

Now, in a traditional CIFS only world, everything would be hunky-dory. I could probably even do the 8+3 filename stuff. But we are wearing big boy pants now, so another test yields a result I do not agree with:

% ./a.out /foo/grabba/yabba/.cshrc
path = </foo/grabba/yabba/.cshrc>
ext  = <cshrc>
base = <>
file = <.cshrc>

I would argue that the base name is '.cshrc' and there is no extension.

Anyone have any different views?


Originally posted on Kool Aid Served Daily
Copyright (C) 2008, Kool Aid Served Daily

Trackback URL: http://blogs.sun.com/tdh/entry/exploring_pulling_apart_a_path
Comments:

shouldn't you canonicalize? consider

/foo//bar
/foo/
/foo/.

etc.

Posted by peter honeyman on January 23, 2008 at 12:33 AM CST #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed
Copyright (C) 2007, Kool Aid Served Daily