/* Distributed Checksum Clearinghouse * * Copyright (c) 2006 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 for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * Parties not eligible to receive a license under this agreement can * obtain a commercial license to use DCC and permission to use * U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/ * or by email to nospam@commtouch.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.50-1.21 $Revision$ */ #include "dcc_defs.h" #ifdef DCC_WIN32 #include #endif DCC_PATH dcc_homedir; int dcc_homedir_len = 2; /* (ensure comparisons fail) */ /* make an absolute pathname from a file name and an optional suffix */ u_char /* 0=too long */ fnm2path(DCC_PATH path, const char *nm, const char *suffix) { DCC_PATH tmp; int i; #ifdef DCC_WIN32 char *p; DWORD lasterror; #else const char *s; char c, *t, *p; #endif /* the answer is the input pathname if it is null or absolute */ 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)) { path[0] = '\0'; return 0; } /* 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 an absolute pathname from a file name for printing */ const char * fnm2path_err(DCC_PATH path, const char *nm) { return fnm2path(path, nm, 0) ? path : nm; } /* make an absolute pathname from a file name that must be good */ void fnm2path_good(DCC_PATH path, const char *nm, const char* suffix) { if (!fnm2path(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) { if (path[dcc_homedir_len] != '/' || path[dcc_homedir_len+1] == '\0' || strncmp(path, dcc_homedir, dcc_homedir_len)) return path; return path + dcc_homedir_len+1; } /* change to the DCC home directory */ u_char /* 0=failed 1=ok */ dcc_cdhome(DCC_EMSG emsg, const char *newdir) { 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 (!fnm2path(tmp, newdir, 0)) { dcc_pemsg(EX_NOINPUT, emsg, "DCC home directory \"%s\" too long", 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); #else if (0 > chdir(tmp)) { dcc_pemsg(EX_NOINPUT, emsg, "chdir(%s): %s", tmp, ERROR_STR()); result = 0; } else if (*tmp == '/' ||!getcwd(dcc_homedir, sizeof(dcc_homedir))) { BUFCPY(dcc_homedir, tmp); } #endif dcc_homedir_len = strlen(dcc_homedir); return result; }