1 /* @(#)lxchdir.c 1.1 11/10/21 Copyright 2004-2011 J. Schilling */ 2 /* 3 * Long path name aware chdir(). 4 * 5 * The code has been adopted from libfind. 6 * 7 * Copyright (c) 2004-2011 J. Schilling 8 */ 9 /* 10 * The contents of this file are subject to the terms of the 11 * Common Development and Distribution License, Version 1.0 only 12 * (the "License"). You may not use this file except in compliance 13 * with the License. 14 * 15 * See the file CDDL.Schily.txt in this distribution for details. 16 * A copy of the CDDL is also available via the Internet at 17 * http://www.opensource.org/licenses/cddl1.txt 18 * 19 * When distributing Covered Code, include this CDDL HEADER in each 20 * file and include the License file CDDL.Schily.txt from this distribution. 21 */ 22 23 #include <schily/unistd.h> 24 #include <schily/types.h> 25 #include <schily/fcntl.h> 26 #include <schily/maxpath.h> 27 #include <schily/string.h> 28 #include <schily/errno.h> 29 #include <schily/standard.h> 30 #include <schily/schily.h> 31 #include "at-defs.h" 32 33 #ifndef ENAMETOOLONG 34 #define ENAMETOOLONG EINVAL 35 #endif 36 37 EXPORT int lxchdir __PR((char *p)); 38 LOCAL int xchdir __PR((char *p)); 39 40 EXPORT int lxchdir(p)41lxchdir(p) 42 char *p; 43 { 44 if (chdir(p) < 0) { 45 if (geterrno() != ENAMETOOLONG) 46 return (-1); 47 48 return (xchdir(p)); 49 } 50 return (0); 51 } 52 53 LOCAL int xchdir(p)54xchdir(p) 55 char *p; 56 { 57 char *p2; 58 BOOL first = TRUE; 59 60 while (*p) { 61 if ((p2 = strchr(p, '/')) != NULL) 62 *p2 = '\0'; 63 64 if (first && p2 && p[0] == '\0') { 65 if (chdir("/") < 0) 66 return (-1); 67 } else { 68 /* 69 * If this is not the first chdir() and we are doing a 70 * multi hop chdir(), we may be on an undefined 71 * intermediate directory. Mark this case by returning 72 * -2 instead of -1. 73 */ 74 if (chdir(p) < 0) 75 return (first?-1:-2); 76 } 77 if (p2 == NULL) 78 break; 79 *p2 = '/'; 80 p = &p2[1]; 81 first = FALSE; 82 } 83 return (0); 84 } 85