1 /* $Source: /u/mark/src/pax/RCS/pathname.c,v $ 2 * 3 * $Revision: 1.2 $ 4 * 5 * pathname.c - directory/pathname support functions 6 * 7 * DESCRIPTION 8 * 9 * These functions provide directory/pathname support for PAX 10 * 11 * AUTHOR 12 * 13 * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) 14 * 15 * Sponsored by The USENIX Association for public distribution. 16 * 17 * Copyright (c) 1989 Mark H. Colburn. 18 * All rights reserved. 19 * 20 * Redistribution and use in source and binary forms are permitted 21 * provided that the above copyright notice is duplicated in all such 22 * forms and that any documentation, advertising materials, and other 23 * materials related to such distribution and use acknowledge that the 24 * software was developed * by Mark H. Colburn and sponsored by The 25 * USENIX Association. 26 * 27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 30 * 31 * $Log: pathname.c,v $ 32 * Revision 1.2 89/02/12 10:05:13 mark 33 * 1.2 release fixes 34 * 35 * Revision 1.1 88/12/23 18:02:21 mark 36 * Initial revision 37 * 38 */ 39 40 #ifndef lint 41 static char *ident = "$Id: pathname.c,v 1.2 89/02/12 10:05:13 mark Exp $"; 42 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; 43 #endif /* ! lint */ 44 45 46 /* Headers */ 47 48 #include "pax.h" 49 50 51 /* dirneed - checks for the existance of directories and possibly create 52 * 53 * DESCRIPTION 54 * 55 * Dirneed checks to see if a directory of the name pointed to by name 56 * exists. If the directory does exist, then dirneed returns 0. If 57 * the directory does not exist and the f_dir_create flag is set, 58 * then dirneed will create the needed directory, recursively creating 59 * any needed intermediate directory. 60 * 61 * If f_dir_create is not set, then no directories will be created 62 * and a value of -1 will be returned if the directory does not 63 * exist. 64 * 65 * PARAMETERS 66 * 67 * name - name of the directory to create 68 * 69 * RETURNS 70 * 71 * Returns a 0 if the creation of the directory succeeded or if the 72 * directory already existed. If the f_dir_create flag was not set 73 * and the named directory does not exist, or the directory creation 74 * failed, a -1 will be returned to the calling routine. 75 */ 76 77 #ifdef __STDC__ 78 79 int dirneed(char *name) 80 81 #else 82 83 int dirneed(name) 84 char *name; 85 86 #endif 87 { 88 char *cp; 89 char *last; 90 int ok; 91 static Stat sb; 92 93 last = (char *)NULL; 94 for (cp = name; *cp;) { 95 if (*cp++ == '/') { 96 last = cp; 97 } 98 } 99 if (last == (char *)NULL) { 100 return (STAT(".", &sb)); 101 } 102 *--last = '\0'; 103 ok = STAT(*name ? name : ".", &sb) == 0 104 ? ((sb.sb_mode & S_IFMT) == S_IFDIR) 105 : (f_dir_create && dirneed(name) == 0 && dirmake(name, &sb) == 0); 106 *last = '/'; 107 return (ok ? 0 : -1); 108 } 109 110 111 /* nameopt - optimize a pathname 112 * 113 * DESCRIPTION 114 * 115 * Confused by "<symlink>/.." twistiness. Returns the number of final 116 * pathname elements (zero for "/" or ".") or -1 if unsuccessful. 117 * 118 * PARAMETERS 119 * 120 * char *begin - name of the path to optimize 121 * 122 * RETURNS 123 * 124 * Returns 0 if successful, non-zero otherwise. 125 * 126 */ 127 128 #ifdef __STDC__ 129 130 int nameopt(char *begin) 131 132 #else 133 134 int nameopt(begin) 135 char *begin; 136 137 #endif 138 { 139 char *name; 140 char *item; 141 int idx; 142 int absolute; 143 char *element[PATHELEM]; 144 145 absolute = (*(name = begin) == '/'); 146 idx = 0; 147 for (;;) { 148 if (idx == PATHELEM) { 149 warn(begin, "Too many elements"); 150 return (-1); 151 } 152 while (*name == '/') { 153 ++name; 154 } 155 if (*name == '\0') { 156 break; 157 } 158 element[idx] = item = name; 159 while (*name && *name != '/') { 160 ++name; 161 } 162 if (*name) { 163 *name++ = '\0'; 164 } 165 if (strcmp(item, "..") == 0) { 166 if (idx == 0) { 167 if (!absolute) { 168 ++idx; 169 } 170 } else if (strcmp(element[idx - 1], "..") == 0) { 171 ++idx; 172 } else { 173 --idx; 174 } 175 } else if (strcmp(item, ".") != 0) { 176 ++idx; 177 } 178 } 179 if (idx == 0) { 180 element[idx++] = absolute ? "" : "."; 181 } 182 element[idx] = (char *)NULL; 183 name = begin; 184 if (absolute) { 185 *name++ = '/'; 186 } 187 for (idx = 0; item = element[idx]; ++idx, *name++ = '/') { 188 while (*item) { 189 *name++ = *item++; 190 } 191 } 192 *--name = '\0'; 193 return (idx); 194 } 195 196 197 /* dirmake - make a directory 198 * 199 * DESCRIPTION 200 * 201 * Dirmake makes a directory with the appropritate permissions. 202 * 203 * PARAMETERS 204 * 205 * char *name - Name of directory make 206 * Stat *asb - Stat structure of directory to make 207 * 208 * RETURNS 209 * 210 * Returns zero if successful, -1 otherwise. 211 * 212 */ 213 214 #ifdef __STDC__ 215 216 int dirmake(char *name, Stat *asb) 217 218 #else 219 220 int dirmake(name, asb) 221 char *name; 222 Stat *asb; 223 224 #endif 225 { 226 if (mkdir(name, (int) (asb->sb_mode & S_IPOPN)) < 0) { 227 return (-1); 228 } 229 if (asb->sb_mode & S_IPEXE) { 230 chmod(name, (int) (asb->sb_mode & S_IPERM)); 231 } 232 if (f_owner) { 233 chown(name, (int) asb->sb_uid, (int) asb->sb_gid); 234 } 235 return (0); 236 } 237