1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*
Copyright (C) 2010, 2011
Rocky Bernstein <rocky@gnu.org>
Diego 'Flameeyes' Pettenò
Thomas Schmitt
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
POSIX realpath if that's around, and something like it if not.
To compile as a standalone program:
gcc -Wall -g -I../.. -DHAVE_CONFIG_H -DSTANDALONE -o realpath realpath.c
*/
/*
Make sure we handle:
- resolve relative links like /dev/cdrom -> sr2
- abort on cyclic linking like /dev/cdrom -> /dev/cdrom
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include <ctype.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_UNISTD_H /* readlink */
# include <unistd.h>
#endif
#ifdef HAVE_INTTYPES_H
# include "inttypes.h"
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#include <cdio/util.h>
/*! cdio_realpath() same as POSIX.1-2001 realpath if that's
around. If not we do poor-man's simulation of that behavior. */
char *cdio_realpath (const char *psz_src_path, char *psz_resolved_path) {
#ifdef HAVE_REALPATH
psz_resolved_path = realpath(psz_src_path, psz_resolved_path);
#elif defined(HAVE_READLINK)
char tmp_src[PATH_MAX+1];
char tmp_dst[PATH_MAX+1];
char *p_adr;
int i, len;
const int loop_limit = 100;
strcpy(tmp_src, psz_src_path);
/* FIXME:
remove loop and change with stat before and after readlink
which looks direct symlink. Rely on errno to figure out other
non-existent or looped symlinks.
*/
for(i = 0; i < loop_limit; i++) {
len = readlink(tmp_src, tmp_dst, PATH_MAX);
if (-1 == len) {
/* Right now we expect a "not symlink" error. However after
we put in the stat() suggested above, there won't be a symlink
error and we should start reporting what the failure is.
*/
break;
} else {
tmp_dst[len] = '\0';
if (tmp_dst[0] != '/') {
/* Take care of relative link like /dev/cdrom -> sr2 */
p_adr = strrchr(tmp_src, '/');
if (p_adr != NULL) {
strncpy(p_adr + 1, tmp_dst, PATH_MAX - (p_adr + 1 - tmp_src));
} else {
strncpy(tmp_src, tmp_dst, PATH_MAX);
}
} else {
strncpy(tmp_src, tmp_dst, PATH_MAX);
}
tmp_src[PATH_MAX - 1] = 0; /* strncpy() does not always set a 0 */
}
}
strncpy(psz_resolved_path, tmp_src, PATH_MAX);
#else
strncpy(psz_resolved_path, psz_src_path, PATH_MAX);
#endif
return psz_resolved_path;
}
#ifdef STANDALONE
int main(int argc, char **argv)
{
int i;
char dest[PATH_MAX];
if (argc < 2) {
fprintf(stderr, "Usage: %s path [path ...]\n", argv[0]);
fprintf(stderr,
" Resolve symbolic links\n");
exit(1);
}
for (i= 1; i < argc; i++) {
dest[0] = 0;
cdio_realpath (argv[i], dest);
printf("%s -> %s\n", argv[i], dest);
}
exit(0);
}
#endif
|