Back to index

enigmail  1.4.3
pathsub.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*
00038 ** Pathname subroutines.
00039 **
00040 ** Brendan Eich, 8/29/95
00041 */
00042 #include <assert.h>
00043 #include <sys/types.h>
00044 #include <dirent.h>
00045 #include <errno.h>
00046 #include <stdarg.h>
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <unistd.h>
00051 #include <sys/stat.h>
00052 #include "pathsub.h"
00053 
00054 #ifdef USE_REENTRANT_LIBC
00055 #include <libc_r.h>
00056 #endif
00057 
00058 #ifdef SUNOS4
00059 #include "sunos4.h"
00060 #endif
00061 
00062 #ifndef D_INO
00063 #define D_INO d_ino
00064 #endif
00065 
00066 char *program;
00067 
00068 void
00069 fail(char *format, ...)
00070 {
00071     int error;
00072     va_list ap;
00073 
00074 #ifdef USE_REENTRANT_LIBC
00075     R_STRERROR_INIT_R();
00076 #endif
00077 
00078     error = errno;
00079     fprintf(stderr, "%s: ", program);
00080     va_start(ap, format);
00081     vfprintf(stderr, format, ap);
00082     va_end(ap);
00083     if (error) {
00084 
00085 #ifdef USE_REENTRANT_LIBC
00086     R_STRERROR_R(errno);
00087        fprintf(stderr, ": %s", r_strerror_r);
00088 #else
00089        fprintf(stderr, ": %s", strerror(errno));
00090 #endif
00091     }
00092 
00093     putc('\n', stderr);
00094     exit(1);
00095 }
00096 
00097 char *
00098 getcomponent(char *path, char *name)
00099 {
00100     if (*path == '\0')
00101        return 0;
00102     if (*path == '/') {
00103        *name++ = '/';
00104     } else {
00105        do {
00106            *name++ = *path++;
00107        } while (*path != '/' && *path != '\0');
00108     }
00109     *name = '\0';
00110     while (*path == '/')
00111        path++;
00112     return path;
00113 }
00114 
00115 #ifdef LAME_READDIR
00116 #include <sys/param.h>
00117 /*
00118 ** The static buffer in Unixware's readdir is too small.
00119 */
00120 struct dirent *readdir(DIR *d)
00121 {
00122         static struct dirent *buf = NULL;
00123 
00124         if(buf == NULL)
00125                 buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN);
00126         return(readdir_r(d, buf));
00127 }
00128 #endif
00129 
00130 char *
00131 ino2name(ino_t ino)
00132 {
00133     DIR *dp;
00134     struct dirent *ep;
00135     char *name;
00136 
00137     dp = opendir("..");
00138     if (!dp)
00139        fail("cannot read parent directory");
00140     for (;;) {
00141        if (!(ep = readdir(dp)))
00142            fail("cannot find current directory");
00143        if (ep->D_INO == ino)
00144            break;
00145     }
00146     name = xstrdup(ep->d_name);
00147     closedir(dp);
00148     return name;
00149 }
00150 
00151 void *
00152 xmalloc(size_t size)
00153 {
00154     void *p = malloc(size);
00155     if (!p)
00156        fail("cannot allocate %u bytes", size);
00157     return p;
00158 }
00159 
00160 char *
00161 xstrdup(char *s)
00162 {
00163     return strcpy(xmalloc(strlen(s) + 1), s);
00164 }
00165 
00166 char *
00167 xbasename(char *path)
00168 {
00169     char *cp;
00170 
00171     while ((cp = strrchr(path, '/')) && cp[1] == '\0')
00172        *cp = '\0';
00173     if (!cp) return path;
00174     return cp + 1;
00175 }
00176 
00177 void
00178 xchdir(char *dir)
00179 {
00180     if (chdir(dir) < 0)
00181        fail("cannot change directory to %s", dir);
00182 }
00183 
00184 int
00185 relatepaths(char *from, char *to, char *outpath)
00186 {
00187     char *cp, *cp2;
00188     int len;
00189     char buf[NAME_MAX];
00190 
00191     assert(*from == '/' && *to == '/');
00192     for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
00193        if (*cp == '\0')
00194            break;
00195     while (cp[-1] != '/')
00196        cp--, cp2--;
00197     if (cp - 1 == to) {
00198        /* closest common ancestor is /, so use full pathname */
00199        len = strlen(strcpy(outpath, to));
00200        if (outpath[len] != '/') {
00201            outpath[len++] = '/';
00202            outpath[len] = '\0';
00203        }
00204     } else {
00205        len = 0;
00206        while ((cp2 = getcomponent(cp2, buf)) != 0) {
00207            strcpy(outpath + len, "../");
00208            len += 3;
00209        }
00210        while ((cp = getcomponent(cp, buf)) != 0) {
00211            sprintf(outpath + len, "%s/", buf);
00212            len += strlen(outpath + len);
00213        }
00214     }
00215     return len;
00216 }
00217 
00218 void
00219 reversepath(char *inpath, char *name, int len, char *outpath)
00220 {
00221     char *cp, *cp2;
00222     char buf[NAME_MAX];
00223     struct stat sb;
00224 
00225     cp = strcpy(outpath + PATH_MAX - (len + 1), name);
00226     cp2 = inpath;
00227     while ((cp2 = getcomponent(cp2, buf)) != 0) {
00228        if (strcmp(buf, ".") == 0)
00229            continue;
00230        if (strcmp(buf, "..") == 0) {
00231            if (stat(".", &sb) < 0)
00232               fail("cannot stat current directory");
00233            name = ino2name(sb.st_ino);
00234            len = strlen(name);
00235            cp -= len + 1;
00236            strcpy(cp, name);
00237            cp[len] = '/';
00238            free(name);
00239            xchdir("..");
00240        } else {
00241            cp -= 3;
00242            strncpy(cp, "../", 3);
00243            xchdir(buf);
00244        }
00245     }
00246     strcpy(outpath, cp);
00247 }