7 /* file name to directory forest
9 /* #include <dir_forest.h>
11 /* char *dir_forest(buf, path, depth)
16 /* This module implements support for directory forests: a file
17 /* organization that introduces one or more levels of intermediate
18 /* subdirectories in order to reduce the number of files per directory.
20 /* dir_forest() maps a file basename to a directory forest and
21 /* returns the resulting string: file name "abcd" becomes "a/b/"
22 /* and so on. The number of subdirectory levels is adjustable.
26 /* A buffer that is overwritten with the result. The result
27 /* ends in "/" and is null terminated. If a null pointer is
28 /* specified, the result is written to a private buffer that
29 /* is overwritten upon each call.
31 /* A null-terminated string of printable characters. Characters
32 /* special to the file system are not permitted.
33 /* The first subdirectory is named after the first character
34 /* in \fIpath\fR, and so on. When the path is shorter than the
35 /* desired number of subdirectory levels, directory names
36 /* of '_' (underscore) are used as replacement.
38 /* The desired number of subdirectory levels.
40 /* Panic: interface violations. Fatal error: out of memory.
44 /* The Secure Mailer license must be distributed with this software.
47 /* IBM T.J. Watson Research
49 /* Yorktown Heights, NY 10598, USA
57 /* Utility library. */
60 #include "dir_forest.h"
62 /* dir_forest - translate base name to directory forest */
64 char *dir_forest(VSTRING
*buf
, const char *path
, int depth
)
66 const char *myname
= "dir_forest";
67 static VSTRING
*private_buf
= 0;
76 msg_panic("%s: empty path", myname
);
78 msg_panic("%s: depth %d", myname
, depth
);
81 * Your buffer or mine?
85 private_buf
= vstring_alloc(1);
90 * Generate one or more subdirectory levels, depending on the pathname
91 * contents. When the pathname is short, use underscores instead.
92 * Disallow non-printable characters or characters that are special to
96 for (cp
= path
, n
= 0; n
< depth
; n
++) {
97 if ((ch
= *cp
) == 0) {
100 if (!ISPRINT(ch
) || ch
== '.' || ch
== '/')
101 msg_panic("%s: invalid pathname: %s", myname
, path
);
104 VSTRING_ADDCH(buf
, ch
);
105 VSTRING_ADDCH(buf
, '/');
107 VSTRING_TERMINATE(buf
);
110 msg_info("%s: %s -> %s", myname
, path
, vstring_str(buf
));
111 return (vstring_str(buf
));