Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/path/pathcd.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
/*
24
* K. P. Vo
25
* G. S. Fowler
26
* AT&T Research
27
*/
28
29
#include <ast.h>
30
#include <error.h>
31
#include <stk.h>
32
33
#if DEBUG
34
35
#undef PATH_MAX
36
37
#define PATH_MAX 16
38
39
static int
40
vchdir(const char* path)
41
{
42
int n;
43
44
if (strlen(path) >= PATH_MAX)
45
{
46
errno = ENAMETOOLONG;
47
n = -1;
48
}
49
else n = chdir(path);
50
return n;
51
}
52
53
#define chdir(p) vchdir(p)
54
55
#endif
56
57
/*
58
* set the current directory to path
59
* if path is long and home!=0 then pathcd(home,0)
60
* is called on intermediate chdir errors
61
*/
62
63
int
64
pathcd(const char* path, const char* home)
65
{
66
register char* p = (char*)path;
67
register char* s;
68
register int n;
69
int i;
70
int r;
71
72
r = 0;
73
for (;;)
74
{
75
/*
76
* this should work 99% of the time
77
*/
78
79
if (!chdir(p))
80
return r;
81
82
/*
83
* chdir failed
84
*/
85
86
if ((n = strlen(p)) < PATH_MAX)
87
return -1;
88
#ifdef ENAMETOOLONG
89
if (errno != ENAMETOOLONG)
90
return -1;
91
#endif
92
93
/*
94
* path is too long -- copy so it can be modified in place
95
*/
96
97
i = stktell(stkstd);
98
sfputr(stkstd, p, 0);
99
stkseek(stkstd, i);
100
p = stkptr(stkstd, i);
101
for (;;)
102
{
103
/*
104
* get a short prefix component
105
*/
106
107
s = p + PATH_MAX;
108
while (--s >= p && *s != '/');
109
if (s <= p)
110
break;
111
112
/*
113
* chdir to the prefix
114
*/
115
116
*s++ = 0;
117
if (chdir(p))
118
break;
119
120
/*
121
* do the remainder
122
*/
123
124
if ((n -= s - p) < PATH_MAX)
125
{
126
if (chdir(s))
127
break;
128
return r;
129
}
130
p = s;
131
}
132
133
/*
134
* try to recover back to home
135
*/
136
137
if (!(p = (char*)home))
138
return -1;
139
home = 0;
140
r = -1;
141
}
142
}
143
144