Postfix3.3.1
dir_forest.c
[詳解]
1 /*++
2 /* NAME
3 /* dir_forest 3
4 /* SUMMARY
5 /* file name to directory forest
6 /* SYNOPSIS
7 /* #include <dir_forest.h>
8 /*
9 /* char *dir_forest(buf, path, depth)
10 /* VSTRING *buf;
11 /* const char *path;
12 /* int depth;
13 /* DESCRIPTION
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.
17 /*
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.
21 /*
22 /* Arguments:
23 /* .IP buf
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.
28 /* .IP path
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.
35 /* .IP depth
36 /* The desired number of subdirectory levels.
37 /* DIAGNOSTICS
38 /* Panic: interface violations. Fatal error: out of memory.
39 /* LICENSE
40 /* .ad
41 /* .fi
42 /* The Secure Mailer license must be distributed with this software.
43 /* AUTHOR(S)
44 /* Wietse Venema
45 /* IBM T.J. Watson Research
46 /* P.O. Box 704
47 /* Yorktown Heights, NY 10598, USA
48 /*--*/
49 
50 /* System library. */
51 
52 #include <sys_defs.h>
53 #include <ctype.h>
54 
55 /* Utility library. */
56 
57 #include "msg.h"
58 #include "dir_forest.h"
59 
60 /* dir_forest - translate base name to directory forest */
61 
62 char *dir_forest(VSTRING *buf, const char *path, int depth)
63 {
64  const char *myname = "dir_forest";
65  static VSTRING *private_buf = 0;
66  int n;
67  const char *cp;
68  int ch;
69 
70  /*
71  * Sanity checks.
72  */
73  if (*path == 0)
74  msg_panic("%s: empty path", myname);
75  if (depth < 1)
76  msg_panic("%s: depth %d", myname, depth);
77 
78  /*
79  * Your buffer or mine?
80  */
81  if (buf == 0) {
82  if (private_buf == 0)
83  private_buf = vstring_alloc(1);
84  buf = private_buf;
85  }
86 
87  /*
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
91  * the file system.
92  */
93  VSTRING_RESET(buf);
94  for (cp = path, n = 0; n < depth; n++) {
95  if ((ch = *cp) == 0) {
96  ch = '_';
97  } else {
98  if (!ISPRINT(ch) || ch == '.' || ch == '/')
99  msg_panic("%s: invalid pathname: %s", myname, path);
100  cp++;
101  }
102  VSTRING_ADDCH(buf, ch);
103  VSTRING_ADDCH(buf, '/');
104  }
105  VSTRING_TERMINATE(buf);
106 
107  if (msg_verbose > 1)
108  msg_info("%s: %s -> %s", myname, path, vstring_str(buf));
109  return (vstring_str(buf));
110 }
int msg_verbose
Definition: msg.c:177
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define vstring_str(vp)
Definition: vstring.h:71
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
char * dir_forest(VSTRING *buf, const char *path, int depth)
Definition: dir_forest.c:62
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define VSTRING_RESET(vp)
Definition: vstring.h:77
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define ISPRINT(c)
Definition: sys_defs.h:1751
void msg_info(const char *fmt,...)
Definition: msg.c:199