Mercurial > notdcc
view 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 source
/* 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; }