Mercurial > notdcc
diff dcclib/fnm2path.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcclib/fnm2path.c Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,331 @@ +/* Distributed Checksum Clearinghouse + * + * Copyright (c) 2008 by Rhyolite Software, LLC + * + * This agreement is not applicable to any entity which sells anti-spam + * solutions to others or provides an anti-spam solution as part of a + * security solution sold to other entities, or to a private network + * which employs the DCC or uses data provided by operation of the DCC + * but does not provide corresponding data to other users. + * + * Permission to use, copy, modify, and distribute this software without + * changes for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice appear in all + * copies and any distributed versions or copies are either unchanged + * or not called anything similar to "DCC" or "Distributed Checksum + * Clearinghouse". + * + * Parties not eligible to receive a license under this agreement can + * obtain a commercial license to use DCC by contacting Rhyolite Software + * at sales@rhyolite.com. + * + * A commercial license would be for Distributed Checksum and Reputation + * Clearinghouse software. That software includes additional features. This + * free license for Distributed ChecksumClearinghouse Software does not in any + * way grant permision to use Distributed Checksum and Reputation Clearinghouse + * software + * + * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC + * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Rhyolite Software DCC 1.3.103-1.26 $Revision$ + */ + +#include "dcc_defs.h" +#ifdef DCC_WIN32 +#include <direct.h> +#endif + +DCC_PATH dcc_homedir; +int dcc_homedir_len = 2; /* (ensure comparisons fail) */ + + +#ifndef DCC_WIN32 +static u_char +trimpath(DCC_PATH path, const DCC_PATH tmp) +{ + const char *s; + char c, *t, *p; + + + /* trim "//", "/./", "../", "/../", or trailing "/" */ + s = tmp; + if (s[0] == '.' && s[1] == '/') + s += 2; + t = path; + for (;;) { + c = *s++; + if (c != '/') { + *t = c; + if (c == '\0') + break; + ++t; + continue; + } + + /* check character after '/' */ + c = *s; + if (c == '/') /* discard first '/' in "//" */ + continue; + if (c == '\0' /* discard trailing '/' */ + && t != path) + continue; + + if (c != '.') { + *t++ = '/'; + continue; + } + + /* we have seen "/." */ + c = *++s; + if (c == '/') /* discard "/." in "/./" */ + continue; + + /* trim trailing "/." */ + if (c == '\0') + continue; + + if (c != '.' + || (*(s+1) != '/' && *(s+1) != '\0')) { + *t++ = '/'; + *t++ = '.'; + continue; + } + + /* we have "/../" or "/..\0", so remove last name in target */ + *t = '\0'; + p = strrchr(path, '/'); + if (p) { + t = p; + if (t == path) /* convert "/.." to "/" */ + ++t; + } else { + t = path; + } + ++s; /* advance to '\0' or 2nd '/' */ + } + if (path[0] == '\0') { + path[0] = tmp[0] == '/' ? '/' : '.'; + path[1] = '\0'; + } + + return 1; +} +#endif + + + +/* make a relative pathname from a file name and an optional suffix */ +u_char /* 0=too long */ +fnm2rel(DCC_PATH new_path, const char *nm, const char *suffix) +{ +#ifdef DCC_WIN32 + return fnm2abs(new_path, nm, suffix); +#else + DCC_PATH tmp; + int i; + const char *p, *p1; + + /* the answer is the input pathname if it is null */ + if (!nm || *nm == '\0') { + new_path[0] = '\0'; + return 0; + } + + if (suffix) { + p = tmp; + i = snprintf(tmp, sizeof(tmp), "%s%s", nm, suffix); + } else { + p = nm; + i = strlen(p); + } + if (i >= ISZ(tmp)) { + /* too long */ + new_path[0] = '\0'; + return 0; + } + if (p[dcc_homedir_len] == '/' + && !strncmp(p, dcc_homedir, dcc_homedir_len)) { + p1 = p + dcc_homedir_len; + do { + ++p1; + } while (*p1 == '/'); + if (*p1 != '\0') + p = p1; + } + + return trimpath(new_path, p); +#endif +} + + + +/* make pathname from an optional suffix and a file name relative to + * a path or the home directory */ +u_char /* 0=too long */ +fnm2abs(DCC_PATH path, /* put it here */ + const char *nm, const char *suffix) +{ + DCC_PATH tmp; + int i; +#ifdef DCC_WIN32 + char *p; + DWORD lasterror; +#endif + + /* the answer is the input pathname if it is null */ + if (!nm || *nm == '\0') { + path[0] = '\0'; + return 0; + } + + if (!suffix) + suffix = ""; + +#ifdef DCC_WIN32 + i = snprintf(tmp, sizeof(DCC_PATH), "%s%s", nm, suffix); + if (i >= ISZ(DCC_PATH)) { + path[0] = '\0'; + return 0; + } + lasterror = GetLastError(); + GetFullPathName(tmp, sizeof(DCC_PATH), path, &p); + SetLastError(lasterror); + return 1; +#else + if (nm[0] == '/' || dcc_homedir[0] == '\0') { + i = snprintf(tmp, sizeof(tmp), "%s%s", nm, suffix); + } else { + i = snprintf(tmp, sizeof(tmp), "%s/%s%s", + dcc_homedir, nm, suffix); + } + if (i >= ISZ(tmp)) { + /* too long */ + path[0] = '\0'; + return 0; + } + + return trimpath(path, tmp); +#endif +} + + + +/* make an absolute pathname from a file name for printing */ +const char * +fnm2abs_err(DCC_PATH path, const char *nm) +{ + static DCC_PATH pathbuf; + + if (!path) /* obviously not thread safe */ + path = pathbuf; + + return fnm2abs(path, nm, 0) ? path : nm; +} + + + +/* make a relative pathname from a file name that must be good */ +void +fnm2rel_good(DCC_PATH path, const char *nm, const char* suffix) +{ + if (!fnm2rel(path, nm, suffix)) + dcc_logbad(EX_SOFTWARE, "\"%s%s\" is too long", + nm, suffix ? suffix : ""); +} + + + +/* remove initial substring of the home directory */ +const char * +path2fnm(const char *path) +{ + const char *p; + + if (path[dcc_homedir_len] != '/' + || strncmp(path, dcc_homedir, dcc_homedir_len)) + return path; + + p = path+dcc_homedir_len; + do { + ++p; + } while (*p == '/'); + if (*p == '\0') + return path; + return p; +} + + + +/* change to the DCC home directory */ +u_char /* 0=failed 1=ok */ +dcc_cdhome(DCC_EMSG emsg, const char *newdir, u_char rdonly) +{ + DCC_PATH tmp; + u_char result; + + result = 1; + if (!newdir) + newdir = DCC_HOMEDIR; + + if (*newdir == '\0') { + dcc_pemsg(EX_NOINPUT, emsg, + "invalid null DCC home directory"); + newdir = DCC_HOMEDIR; + result = 0; + } + + if (!fnm2abs(tmp, newdir, 0)) { + dcc_pemsg(EX_NOINPUT, emsg, + "bad DCC home directory \"%s\"", newdir); + result = 0; + } +#ifdef DCC_WIN32 + if (!SetCurrentDirectory(tmp)) { + dcc_pemsg(EX_NOINPUT, emsg, "SetCurrentDirectory(%s): %s" , + tmp, ERROR_STR()); + return 0; + } + if (!getcwd(dcc_homedir, sizeof(dcc_homedir))) { + BUFCPY(dcc_homedir, tmp); + dcc_homedir_len = strlen(dcc_homedir); + } +#else + if (0 > chdir(tmp)) { + dcc_pemsg(EX_NOINPUT, emsg, "chdir(%s): %s", + tmp, ERROR_STR()); + result = 0; + } else if (tmp[0] == '/' + || !getcwd(dcc_homedir, sizeof(dcc_homedir))) { + BUFCPY(dcc_homedir, tmp); + dcc_homedir_len = strlen(dcc_homedir); + } + + if (!rdonly && 0 > access(dcc_homedir, W_OK)) { + if ((errno == EACCES || errno == EPERM) + && dcc_real_uid != dcc_effective_uid) { +#ifdef HAVE_EACCESS + dcc_get_priv(); + if (0 > eaccess(dcc_homedir, W_OK)) { + dcc_pemsg(EX_NOINPUT, emsg, "%s: %s", + dcc_homedir, ERROR_STR()); + result = 0; + } + dcc_rel_priv(); +#endif + } else { + dcc_pemsg(EX_NOINPUT, emsg, "%s: %s", + dcc_homedir, ERROR_STR()); + result = 0; + } + } +#endif /* !DCC_WIN32 */ + + return result; +}