diff --git a/lib/driver/.gitignore b/lib/driver/.gitignore index 21035a63..0a420e8d 100644 --- a/lib/driver/.gitignore +++ b/lib/driver/.gitignore @@ -1,11 +1,12 @@ /*.lo /*.o -/.deps -/.libs -/*~ -/Makefile -/Makefile.in -/libcdio.la -/libcdio.la.ver /*.orig /*.rej +/*~ +/.deps +/.libs +/Makefile +/Makefile.in +/follow_symlink +/libcdio.la +/libcdio.la.ver diff --git a/lib/driver/Makefile.am b/lib/driver/Makefile.am index 1be1ad9c..b6e24dae 100644 --- a/lib/driver/Makefile.am +++ b/lib/driver/Makefile.am @@ -67,6 +67,7 @@ libcdio_sources = \ device.c \ disc.c \ ds.c \ + follow_symlink.c \ FreeBSD/freebsd.c \ FreeBSD/freebsd.h \ FreeBSD/freebsd_cam.c \ diff --git a/lib/driver/follow_symlink.c b/lib/driver/follow_symlink.c new file mode 100644 index 00000000..75cd4bc8 --- /dev/null +++ b/lib/driver/follow_symlink.c @@ -0,0 +1,138 @@ +/* + Copyright (C) 2010 + Rocky Bernstein + 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 . +*/ +/* + Resolves symbolic links. + + To compile as a standalone program: + gcc -Wall -g -I../.. -DHAVE_CONFIG_H -DSTANDALONE -o follow_symlink follow_symlink.c +*/ +/* + Make sure we handle: + - resolve relative links like /dev/cdrom -> sr2 + - abort on deep link nesting /dev/cdrom -> /dev/cdrom +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifdef HAVE_STDLIB_H +# include +#endif + +#include + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_UNISTD_H // readlink +# include +#endif + + +#ifdef HAVE_INTTYPES_H +# include "inttypes.h" +#endif + +#ifdef HAVE_LIMITS_H +# include +#endif + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +/*! + Follow symlinks until we have the real device file + (idea taken from libunieject). +*/ + +void cdio_follow_symlink (const char * src, char * dst) { +#ifdef HAVE_READLINK + char tmp_src[PATH_MAX+1]; + char tmp_dst[PATH_MAX+1]; + char *p_adr; + int link_loop_limit = 100, i; + int len; + + strcpy(tmp_src, src); + + /* 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 < link_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(dst, tmp_src, PATH_MAX); + +#else + strncpy(dst, src, PATH_MAX); +#endif + +} + +#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_follow_symlink (argv[i], dest); + printf("%s -> %s\n", argv[i], dest); + } + exit(0); +} +#endif diff --git a/lib/driver/util.c b/lib/driver/util.c index 0cf52ecd..725511a3 100644 --- a/lib/driver/util.c +++ b/lib/driver/util.c @@ -1,7 +1,5 @@ /* - $Id: util.c,v 1.6 2008/04/22 15:29:12 karl Exp $ - - Copyright (C) 2003, 2004, 2005, 2008, 2009 + Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010 Rocky Bernstein Copyright (C) 2000 Herbert Valerio Riedel @@ -24,13 +22,13 @@ #endif #include +#ifdef HAVE_STDLIB_H #include +#endif #include -#include -#include -#ifdef HAVE_UNISTD_H // readlink -#include +#ifdef HAVE_STRING_H +#include #endif #ifdef HAVE_INTTYPES_H @@ -42,12 +40,6 @@ #include #include -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - -static const char _rcsid[] = "$Id: util.c,v 1.6 2008/04/22 15:29:12 karl Exp $"; - size_t _cdio_strlenv(char **str_array) { @@ -155,35 +147,6 @@ cdio_from_bcd8(uint8_t p) return (0xf & p)+(10*(p >> 4)); } -/*! - Follow symlinks until we have the real device file - (idea taken from libunieject). -*/ - -void cdio_follow_symlink (const char * src, char * dst) { -#ifdef HAVE_READLINK - char tmp_src[PATH_MAX+1]; - char tmp_dst[PATH_MAX+1]; - - int len; - - strcpy(tmp_src, src); - while(1) { - len = readlink(tmp_src, tmp_dst, PATH_MAX); - if(len < 0) { - strncpy(dst, tmp_src, PATH_MAX); - return; - } - else { - tmp_dst[len] = '\0'; - strncpy(tmp_src, tmp_dst, PATH_MAX); - } - } -#else - strncpy(dst, src, PATH_MAX); -#endif - -} const char *cdio_version_string = CDIO_VERSION; const unsigned int libcdio_version_num = LIBCDIO_VERSION_NUM;