~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to getcwd.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 1989, 1991, 1993
3
 
 *      The Regents of the University of California.  All rights reserved.
4
 
 *
5
 
 * Redistribution and use in source and binary forms, with or without
6
 
 * modification, are permitted provided that the following conditions
7
 
 * are met:
8
 
 * 1. Redistributions of source code must retain the above copyright
9
 
 *    notice, this list of conditions and the following disclaimer.
10
 
 * 2. Redistributions in binary form must reproduce the above copyright
11
 
 *    notice, this list of conditions and the following disclaimer in the
12
 
 *    documentation and/or other materials provided with the distribution.
13
 
 * 3. Neither the name of the University nor the names of its contributors
14
 
 *    may be used to endorse or promote products derived from this software
15
 
 *    without specific prior written permission.
16
 
 *
17
 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 
 * SUCH DAMAGE.
28
 
 */
29
 
 
30
 
#include <config.h>
31
 
 
32
 
#include <sys/param.h>
33
 
#include <sys/stat.h>
34
 
 
35
 
#include <errno.h>
36
 
#include <stdio.h>
37
 
#ifdef STDC_HEADERS
38
 
# include <stdlib.h>
39
 
# include <stddef.h>
40
 
#else
41
 
# ifdef HAVE_STDLIB_H
42
 
#  include <stdlib.h>
43
 
# endif
44
 
#endif /* STDC_HEADERS */
45
 
#ifdef HAVE_STRING_H
46
 
# include <string.h>
47
 
#endif /* HAVE_STRING_H */
48
 
#ifdef HAVE_STRINGS_H
49
 
# include <strings.h>
50
 
#endif /* HAVE_STRINGS_H */
51
 
#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
52
 
# include <malloc.h>
53
 
#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
54
 
#ifdef HAVE_UNISTD_H
55
 
# include <unistd.h>
56
 
#endif /* HAVE_UNISTD_H */
57
 
#ifdef HAVE_DIRENT_H
58
 
# include <dirent.h>
59
 
# define NAMLEN(dirent) strlen((dirent)->d_name)
60
 
#else
61
 
# define dirent direct
62
 
# define NAMLEN(dirent) (dirent)->d_namlen
63
 
# ifdef HAVE_SYS_NDIR_H
64
 
#  include <sys/ndir.h>
65
 
# endif
66
 
# ifdef HAVE_SYS_DIR_H
67
 
#  include <sys/dir.h>
68
 
# endif
69
 
# ifdef HAVE_NDIR_H
70
 
#  include <ndir.h>
71
 
# endif
72
 
#endif
73
 
 
74
 
#include <compat.h>
75
 
 
76
 
#define ISDOT(dp) \
77
 
        (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
78
 
            (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
79
 
 
80
 
char *
81
 
getcwd(pt, size)
82
 
        char *pt;
83
 
        size_t size;
84
 
{
85
 
        struct dirent *dp;
86
 
        DIR *dir = NULL;
87
 
        dev_t dev;
88
 
        ino_t ino;
89
 
        int first;
90
 
        char *bpt, *bup;
91
 
        struct stat s;
92
 
        dev_t root_dev;
93
 
        ino_t root_ino;
94
 
        size_t ptsize, upsize;
95
 
        int save_errno;
96
 
        char *ept, *eup, *up;
97
 
 
98
 
        /*
99
 
         * If no buffer specified by the user, allocate one as necessary.
100
 
         * If a buffer is specified, the size has to be non-zero.  The path
101
 
         * is built from the end of the buffer backwards.
102
 
         */
103
 
        if (pt) {
104
 
                ptsize = 0;
105
 
                if (!size) {
106
 
                        errno = EINVAL;
107
 
                        return (NULL);
108
 
                }
109
 
                ept = pt + size;
110
 
        } else {
111
 
                if ((pt = malloc(ptsize = 1024 - 4)) == NULL)
112
 
                        return (NULL);
113
 
                ept = pt + ptsize;
114
 
        }
115
 
        bpt = ept - 1;
116
 
        *bpt = '\0';
117
 
 
118
 
        /*
119
 
         * Allocate bytes (1024 - malloc space) for the string of "../"'s.
120
 
         * Should always be enough (it's 340 levels).  If it's not, allocate
121
 
         * as necessary.  Special * case the first stat, it's ".", not "..".
122
 
         */
123
 
        if ((up = malloc(upsize = 1024 - 4)) == NULL)
124
 
                goto err;
125
 
        eup = up + PATH_MAX;
126
 
        bup = up;
127
 
        up[0] = '.';
128
 
        up[1] = '\0';
129
 
 
130
 
        /* Save root values, so know when to stop. */
131
 
        if (stat("/", &s))
132
 
                goto err;
133
 
        root_dev = s.st_dev;
134
 
        root_ino = s.st_ino;
135
 
 
136
 
        errno = 0;                      /* XXX readdir has no error return. */
137
 
 
138
 
        for (first = 1;; first = 0) {
139
 
                /* Stat the current level. */
140
 
                if (lstat(up, &s))
141
 
                        goto err;
142
 
 
143
 
                /* Save current node values. */
144
 
                ino = s.st_ino;
145
 
                dev = s.st_dev;
146
 
 
147
 
                /* Check for reaching root. */
148
 
                if (root_dev == dev && root_ino == ino) {
149
 
                        *--bpt = '/';
150
 
                        /*
151
 
                         * It's unclear that it's a requirement to copy the
152
 
                         * path to the beginning of the buffer, but it's always
153
 
                         * been that way and stuff would probably break.
154
 
                         */
155
 
                        bcopy(bpt, pt, ept - bpt);
156
 
                        free(up);
157
 
                        return (pt);
158
 
                }
159
 
 
160
 
                /*
161
 
                 * Build pointer to the parent directory, allocating memory
162
 
                 * as necessary.  Max length is 3 for "../", the largest
163
 
                 * possible component name, plus a trailing NULL.
164
 
                 */
165
 
                if (bup + 3  + MAXNAMLEN + 1 >= eup) {
166
 
                        char *nup;
167
 
 
168
 
                        if ((nup = realloc(up, upsize *= 2)) == NULL)
169
 
                                goto err;
170
 
                        up = nup;
171
 
                        bup = up;
172
 
                        eup = up + upsize;
173
 
                }
174
 
                *bup++ = '.';
175
 
                *bup++ = '.';
176
 
                *bup = '\0';
177
 
 
178
 
                /* Open and stat parent directory. */
179
 
                if (!(dir = opendir(up)) || fstat(dirfd(dir), &s))
180
 
                        goto err;
181
 
 
182
 
                /* Add trailing slash for next directory. */
183
 
                *bup++ = '/';
184
 
 
185
 
                /*
186
 
                 * If it's a mount point, have to stat each element because
187
 
                 * the inode number in the directory is for the entry in the
188
 
                 * parent directory, not the inode number of the mounted file.
189
 
                 */
190
 
                save_errno = 0;
191
 
                if (s.st_dev == dev) {
192
 
                        for (;;) {
193
 
                                if (!(dp = readdir(dir)))
194
 
                                        goto notfound;
195
 
                                if (dp->d_fileno == ino)
196
 
                                        break;
197
 
                        }
198
 
                } else
199
 
                        for (;;) {
200
 
                                if (!(dp = readdir(dir)))
201
 
                                        goto notfound;
202
 
                                if (ISDOT(dp))
203
 
                                        continue;
204
 
                                bcopy(dp->d_name, bup, NAMLEN(dp) + 1);
205
 
 
206
 
                                /* Save the first error for later. */
207
 
                                if (lstat(up, &s)) {
208
 
                                        if (!save_errno)
209
 
                                                save_errno = errno;
210
 
                                        errno = 0;
211
 
                                        continue;
212
 
                                }
213
 
                                if (s.st_dev == dev && s.st_ino == ino)
214
 
                                        break;
215
 
                        }
216
 
 
217
 
                /*
218
 
                 * Check for length of the current name, preceding slash,
219
 
                 * leading slash.
220
 
                 */
221
 
                if (bpt - pt <= NAMLEN(dp) + (first ? 1 : 2)) {
222
 
                        size_t len, off;
223
 
                        char *npt;
224
 
 
225
 
                        if (!ptsize) {
226
 
                                errno = ERANGE;
227
 
                                goto err;
228
 
                        }
229
 
                        off = bpt - pt;
230
 
                        len = ept - bpt;
231
 
                        if ((npt = realloc(pt, ptsize *= 2)) == NULL)
232
 
                                goto err;
233
 
                        pt = npt;
234
 
                        bpt = pt + off;
235
 
                        ept = pt + ptsize;
236
 
                        bcopy(bpt, ept - len, len);
237
 
                        bpt = ept - len;
238
 
                }
239
 
                if (!first)
240
 
                        *--bpt = '/';
241
 
                bpt -= NAMLEN(dp);
242
 
                bcopy(dp->d_name, bpt, NAMLEN(dp));
243
 
                (void)closedir(dir);
244
 
 
245
 
                /* Truncate any file name. */
246
 
                *bup = '\0';
247
 
        }
248
 
 
249
 
notfound:
250
 
        /*
251
 
         * If readdir set errno, use it, not any saved error; otherwise,
252
 
         * didn't find the current directory in its parent directory, set
253
 
         * errno to ENOENT.
254
 
         */
255
 
        if (!errno)
256
 
                errno = save_errno ? save_errno : ENOENT;
257
 
        /* FALLTHROUGH */
258
 
err:
259
 
        if (ptsize)
260
 
                free(pt);
261
 
        if (up)
262
 
                free(up);
263
 
        if (dir)
264
 
                (void)closedir(dir);
265
 
        return (NULL);
266
 
}