OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [sysdeps/] [linux/] [common/] [getcwd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* These functions find the absolute path to the current working directory.  */
2
 
3
#include <stdlib.h>
4
#include <errno.h>
5
#include <sys/stat.h>
6
#include <dirent.h>
7
#include <string.h>
8
#include <sys/syscall.h>
9
 
10
#ifdef __NR_getcwd
11
 
12
#define __NR___syscall_getcwd __NR_getcwd
13
static inline
14
_syscall2(int, __syscall_getcwd, char *, buf, unsigned long, size);
15
 
16
#else
17
 
18
/* If the syscall is not present, we have to walk up the
19
 * directory tree till we hit the root.  Now we _could_
20
 * use /proc/self/cwd if /proc is mounted... That approach
21
 * is left an an exercise for the reader... */
22
 
23
 
24
/* Seems a few broken filesystems (like coda) don't like this */
25
/* #undef FAST_DIR_SEARCH_POSSIBLE on Linux */
26
 
27
 
28
/* Routine to find the step back down */
29
static char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, int path_size)
30
{
31
        DIR *dp;
32
        struct dirent *d;
33
        char *ptr;
34
        int slen;
35
        struct stat st;
36
 
37
#ifdef FAST_DIR_SEARCH_POSSIBLE
38
        /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */
39
        int slow_search = (sizeof(ino_t) != sizeof(d->d_ino));
40
#endif
41
 
42
        if (stat(path_buf, &st) < 0) {
43
                goto oops;
44
        }
45
#ifdef FAST_DIR_SEARCH_POSSIBLE
46
        if (this_dev != st.st_dev)
47
                slow_search = 1;
48
#endif
49
 
50
        slen = strlen(path_buf);
51
        ptr = path_buf + slen - 1;
52
        if (*ptr != '/') {
53
                if (slen + 2 > path_size) {
54
                        goto oops;
55
                }
56
                strcpy(++ptr, "/");
57
                slen++;
58
        }
59
        slen++;
60
 
61
        dp = opendir(path_buf);
62
        if (dp == 0) {
63
            goto oops;
64
        }
65
 
66
        while ((d = readdir(dp)) != 0) {
67
#ifdef FAST_DIR_SEARCH_POSSIBLE
68
                if (slow_search || this_ino == d->d_ino) {
69
#endif
70
                        if (slen + strlen(d->d_name) > path_size) {
71
                            goto oops;
72
                        }
73
                        strcpy(ptr + 1, d->d_name);
74
                        if (stat(path_buf, &st) < 0)
75
                                continue;
76
                        if (st.st_ino == this_ino && st.st_dev == this_dev) {
77
                                closedir(dp);
78
                                return path_buf;
79
                        }
80
#ifdef FAST_DIR_SEARCH_POSSIBLE
81
                }
82
#endif
83
        }
84
 
85
        closedir(dp);
86
        return 0;
87
 
88
oops:
89
        __set_errno(ERANGE);
90
        return 0;
91
}
92
 
93
/* Routine to go up tree */
94
static char *recurser(char *path_buf, int path_size, dev_t root_dev, ino_t root_ino)
95
{
96
        struct stat st;
97
        dev_t this_dev;
98
        ino_t this_ino;
99
 
100
        if (stat(path_buf, &st) < 0) {
101
            if (errno != EFAULT)
102
                goto oops;
103
            return 0;
104
        }
105
        this_dev = st.st_dev;
106
        this_ino = st.st_ino;
107
        if (this_dev == root_dev && this_ino == root_ino) {
108
                if (path_size < 2) {
109
                    goto oops;
110
                }
111
                strcpy(path_buf, "/");
112
                return path_buf;
113
        }
114
        if (strlen(path_buf) + 4 > path_size) {
115
            goto oops;
116
        }
117
        strcat(path_buf, "/..");
118
        if (recurser(path_buf, path_size, root_dev, root_ino) == 0)
119
                return 0;
120
 
121
        return search_dir(this_dev, this_ino, path_buf, path_size);
122
oops:
123
        __set_errno(ERANGE);
124
        return 0;
125
}
126
 
127
static inline
128
int __syscall_getcwd(char * buf, unsigned long size)
129
{
130
    int len;
131
    char *cwd;
132
    struct stat st;
133
    int olderrno;
134
 
135
    olderrno = errno;
136
    len = -1;
137
    cwd = recurser(buf, size, st.st_dev, st.st_ino);
138
    if (cwd) {
139
        len = strlen(buf);
140
        __set_errno(olderrno);
141
    }
142
    return len;
143
}
144
 
145
#endif
146
 
147
char *getcwd(char *buf, int size)
148
{
149
    int ret;
150
    char *path;
151
    size_t alloc_size = size;
152
 
153
    if (size == 0) {
154
        if (buf != NULL) {
155
            __set_errno(EINVAL);
156
            return NULL;
157
        }
158
        alloc_size = PATH_MAX;
159
    }
160
    path=buf;
161
    if (buf == NULL) {
162
        path = malloc(alloc_size);
163
        if (path == NULL)
164
            return NULL;
165
    }
166
    ret = __syscall_getcwd(path, alloc_size);
167
    if (ret >= 0)
168
    {
169
        if (buf == NULL && size == 0)
170
            buf = realloc(path, ret);
171
        if (buf == NULL)
172
            buf = path;
173
        return buf;
174
    }
175
    if (buf == NULL)
176
        free (path);
177
    return NULL;
178
}
179
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.