5
/* file name to directory forest
7
/* #include <dir_forest.h>
9
/* char *dir_forest(buf, path, depth)
14
/* This module implements support for directory forests: a file
15
/* organization that introduces one or more levels of intermediate
16
/* subdirectories in order to reduce the number of files per directory.
18
/* dir_forest() maps a file basename to a directory forest and
19
/* returns the resulting string: file name "abcd" becomes "a/b/"
20
/* and so on. The number of subdirectory levels is adjustable.
24
/* A buffer that is overwritten with the result. The result
25
/* ends in "/" and is null terminated. If a null pointer is
26
/* specified, the result is written to a private buffer that
27
/* is overwritten upon each call.
29
/* A null-terminated string of printable characters. Characters
30
/* special to the file system are not permitted.
31
/* The first subdirectory is named after the first character
32
/* in \fIpath\fR, and so on. When the path is shorter than the
33
/* desired number of subdirectory levels, directory names
34
/* of '_' (underscore) are used as replacement.
36
/* The desired number of subdirectory levels.
38
/* Panic: interface violations. Fatal error: out of memory.
42
/* The Secure Mailer license must be distributed with this software.
45
/* IBM T.J. Watson Research
47
/* Yorktown Heights, NY 10598, USA
55
/* Utility library. */
58
#include "dir_forest.h"
60
/* dir_forest - translate base name to directory forest */
62
char *dir_forest(VSTRING *buf, const char *path, int depth)
64
char *myname = "dir_forest";
65
static VSTRING *private_buf = 0;
74
msg_panic("%s: empty path", myname);
76
msg_panic("%s: depth %d", myname, depth);
79
* Your buffer or mine?
83
private_buf = vstring_alloc(1);
88
* Generate one or more subdirectory levels, depending on the pathname
89
* contents. When the pathname is short, use underscores instead.
90
* Disallow non-printable characters or characters that are special to
94
for (cp = path, n = 0; n < depth; n++) {
95
if ((ch = *cp) == 0) {
98
if (!ISPRINT(ch) || ch == '.' || ch == '/')
99
msg_panic("%s: invalid pathname: %s", myname, path);
102
VSTRING_ADDCH(buf, ch);
103
VSTRING_ADDCH(buf, '/');
105
VSTRING_TERMINATE(buf);
108
msg_info("%s: %s -> %s", myname, path, vstring_str(buf));
109
return (vstring_str(buf));