2 Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
17 * Netatalk utility functions
22 #endif /* HAVE_CONFIG_H */
29 #include <sys/types.h>
36 #include <atalk/adouble.h>
38 #include <atalk/afp.h>
39 #include <atalk/logger.h>
40 #include <atalk/vfs.h>
41 #include <atalk/util.h>
42 #include <atalk/unix.h>
43 #include <atalk/compat.h>
45 /* close all FDs >= a specified value */
46 static void closeall(int fd)
48 int fdlimit = sysconf(_SC_OPEN_MAX);
57 * Fork, exit parent, setsid(), optionally chdir("/"), optionally close all fds
59 * returns -1 on failure, but you can't do much except exit in that case
60 * since we may already have forked
62 int daemonize(int nochdir, int noclose)
90 open("/dev/null",O_RDWR);
98 static uid_t saved_uid = -1;
101 * seteuid(0) and back, if either fails and panic != 0 we PANIC
103 void become_root(void)
106 saved_uid = geteuid();
108 AFP_PANIC("Can't seteuid(0)");
112 void unbecome_root(void)
115 if (saved_uid == -1 || seteuid(saved_uid) < 0)
116 AFP_PANIC("Can't seteuid back");
122 * @brief get cwd in static buffer
124 * @returns pointer to path or pointer to error messages on error
126 const char *getcwdpath(void)
128 static char cwd[MAXPATHLEN + 1];
131 if ((p = getcwd(cwd, MAXPATHLEN)) != NULL)
134 return strerror(errno);
138 * @brief Request absolute path
140 * @returns Absolute filesystem path to object
142 const char *fullpathname(const char *name)
144 static char wd[MAXPATHLEN + 1];
149 if (getcwd(wd , MAXPATHLEN)) {
150 strlcat(wd, "/", MAXPATHLEN);
151 strlcat(wd, name, MAXPATHLEN);
153 strlcpy(wd, name, MAXPATHLEN);
160 * Takes a buffer with a path, strips slashs, returns basename
164 * "[/][dir/[...]]file"
166 * "[/][dir/[...]]dir/[/]"
167 * Result is "file" or "dir"
169 * @returns pointer to basename in path buffer, buffer is possibly modified
171 char *stripped_slashes_basename(char *p)
173 int i = strlen(p) - 1;
174 while (i > 0 && p[i] == '/')
176 return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p);
180 * @brief symlink safe chdir replacement
182 * Only chdirs to dir if it doesn't contain symlinks.
184 * @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror
186 int lchdir(const char *dir)
188 char buf[MAXPATHLEN+1];
189 char cwd[MAXPATHLEN+1];
194 dir is a canonical path (without "../" "./" "//" )
199 if (getcwd(cwd, MAXPATHLEN) == NULL)
207 * chdir request | realpath result | ret
208 * (after getwcwd) | |
209 * =======================================
212 * /a/b/. | /c/d/e/f | 1
214 if (getcwd(buf, MAXPATHLEN) == NULL)
219 /* relative path requested,
222 for (; cwd[i]; i++) {
223 if (buf[i] != cwd[i])
234 for (i = 0; test[i]; i++) {
235 if (test[i] != dir[i]) {
254 * Store n random bytes an buf
256 void randombytes(void *buf, int n)
258 char *p = (char *)buf;
262 if ((fd = open("/dev/urandom", O_RDONLY)) != -1) {
263 /* generate from /dev/urandom */
264 if (read(fd, buf, n) != n) {
269 /* fd now != -1, so srandom wont be called below */
274 gettimeofday(&tv, NULL);
275 srandom((unsigned int)tv.tv_usec);
276 for (i=0 ; i < n ; i++)
277 p[i] = random() & 0xFF;
283 int gmem(gid_t gid, int ngroups, gid_t *groups)
287 for ( i = 0; i < ngroups; i++ ) {
288 if ( groups[ i ] == gid ) {