]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/unix.c
Move lchdir() to libatalk/util/unix.c and use that in catsearch.c.
[netatalk.git] / libatalk / util / unix.c
1 /*
2   $Id: unix.c,v 1.4 2010-02-19 11:29:52 franklahm Exp $
3   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 */
15
16 /*!
17  * @file
18  * Netatalk utility functions
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H */
24
25 #include <unistd.h>
26 #include <stdint.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <dirent.h>
34
35 #include <atalk/adouble.h>
36 #include <atalk/ea.h>
37 #include <atalk/afp.h>
38 #include <atalk/logger.h>
39 #include <atalk/volume.h>
40 #include <atalk/vfs.h>
41 #include <atalk/util.h>
42 #include <atalk/unix.h>
43
44 /*!
45  * @brief get cwd in static buffer
46  *
47  * @returns pointer to path or pointer to error messages on error
48  */
49 const char *getcwdpath(void)
50 {
51     static char cwd[MAXPATHLEN + 1];
52     char *p;
53
54     if ((p = getcwd(cwd, MAXPATHLEN)) != NULL)
55         return p;
56     else
57         return strerror(errno);
58 }
59
60 /*!
61  * @brief symlink safe chdir replacement
62  *
63  * Only chdirs to dir if it doesn't contain symlinks.
64  *
65  * @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror
66  */
67 int lchdir(const char *dir)
68 {
69     int ret = 0;
70     char buf[MAXPATHLEN+1];
71 #ifdef REALPATH_TAKES_NULL
72     char *rpath = NULL;
73 #else
74     char rpath[MAXPATHLEN+1];
75 #endif
76
77     /* dir might be an relative or an absolute path */
78     if (dir[0] == '/') {
79         /* absolute path, just make sure buf is prepared for strlcat */
80         buf[0] = 0;
81     } else {
82         /* relative path, push cwd int buf */
83         if (getcwd(buf, MAXPATHLEN) == NULL)
84             return -1;
85         if (strlcat(buf, "/", MAXPATHLEN) >= MAXPATHLEN)
86             return -1;
87     }
88
89     if (strlcat(buf, dir, MAXPATHLEN) >= MAXPATHLEN)
90         return -1;
91
92 #ifdef REALPATH_TAKES_NULL
93     if ((rpath = realpath(dir, NULL)) == NULL) {
94 #else
95     if (realpath(dir, rpath) == NULL) {
96 #endif
97         ret = -1;
98         goto exit;
99     }
100
101     /* 
102      * Cases:
103      * chdir request   | realpath result | ret
104      * (after getwcwd) |                 |
105      * =======================================
106      * /a/b/.          | /a/b            | 0
107      * /a/b/.          | /c              | 1
108      * /a/b/.          | /c/d/e/f        | 1
109      */
110     ret = 0;
111     for (int i = 0; rpath[i]; i++) {
112         if (buf[i] != rpath[i]) {
113             ret = 1;
114             goto exit;
115         }
116     }
117
118     if (chdir(dir) != 0) {
119         ret = -1;
120         goto exit;
121     }
122
123 exit:
124 #ifdef REALPATH_TAKES_NULL
125     free(rpath);
126 #endif
127     return ret;
128 }