• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/libatalk/util/
1/*
2  Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
3
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.
8
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.
13*/
14
15/*!
16 * @file
17 * Netatalk utility functions
18 */
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif /* HAVE_CONFIG_H */
23
24#include <unistd.h>
25#include <stdint.h>
26#include <errno.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <dirent.h>
33#include <sys/time.h>
34#include <time.h>
35
36#include <atalk/adouble.h>
37#include <atalk/ea.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
44/*!
45 * @brief get cwd in static buffer
46 *
47 * @returns pointer to path or pointer to error messages on error
48 */
49const 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 * Takes a buffer with a path, strips slashs, returns basename
62 *
63 * @param p (rw) path
64 *        path may be
65 *          "[/][dir/[...]]file"
66 *        or
67 *          "[/][dir/[...]]dir/[/]"
68 *        Result is "file" or "dir"
69 *
70 * @returns pointer to basename in path buffer, buffer is possibly modified
71 */
72char *stripped_slashes_basename(char *p)
73{
74    int i = strlen(p) - 1;
75    while (i > 0 && p[i] == '/')
76        p[i--] = 0;
77    return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p);
78}
79
80/*!
81 * @brief symlink safe chdir replacement
82 *
83 * Only chdirs to dir if it doesn't contain symlinks.
84 *
85 * @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror
86 */
87int lchdir(const char *dir)
88{
89    char buf[MAXPATHLEN+1];
90    char cwd[MAXPATHLEN+1];
91    char *test;
92    int  i;
93
94    /*
95     dir is a canonical path (without "../" "./" "//" )
96     but may end with a /
97    */
98    *cwd = 0;
99    if (*dir != '/') {
100        if (getcwd(cwd, MAXPATHLEN) == NULL)
101            return -1;
102    }
103    if (chdir(dir) != 0)
104        return -1;
105
106    /*
107     * Cases:
108     * chdir request   | realpath result | ret
109     * (after getwcwd) |                 |
110     * =======================================
111     * /a/b/.          | /a/b            | 0
112     * /a/b/.          | /c              | 1
113     * /a/b/.          | /c/d/e/f        | 1
114     */
115    if (getcwd(buf, MAXPATHLEN) == NULL)
116        return 1;
117
118    i = 0;
119    if (*cwd) {
120        /* relative path requested,
121         * Same directory?
122        */
123        for (; cwd[i]; i++) {
124            if (buf[i] != cwd[i])
125                return 1;
126        }
127        if (buf[i]) {
128            if (buf[i] != '/')
129                return 1;
130            i++;
131        }
132    }
133
134    test = &buf[i];
135    for (i = 0; test[i]; i++) {
136        if (test[i] != dir[i]) {
137            return 1;
138        }
139    }
140    /* trailing '/' ? */
141    if (!dir[i])
142        return 0;
143
144    if (dir[i] != '/')
145        return 1;
146
147    i++;
148    if (dir[i])
149        return 1;
150
151    return 0;
152}
153
154/*!
155 * Store n random bytes an buf
156 */
157void randombytes(void *buf, int n)
158{
159    char *p = (char *)buf;
160    int fd, i;
161    struct timeval tv;
162
163    if ((fd = open("/dev/urandom", O_RDONLY)) != -1) {
164        /* generate from /dev/urandom */
165        if (read(fd, buf, n) != n) {
166            close(fd);
167            fd = -1;
168        } else {
169            close(fd);
170            /* fd now != -1, so srandom wont be called below */
171        }
172    }
173
174    if (fd == -1) {
175        gettimeofday(&tv, NULL);
176        srandom((unsigned int)tv.tv_usec);
177        for (i=0 ; i < n ; i++)
178            p[i] = random() & 0xFF;
179    }
180
181    return;
182}
183