Blame lib/driver/realpath.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2010, 2011
Packit dd8086
  Rocky Bernstein <rocky@gnu.org>
Packit dd8086
  Diego 'Flameeyes' Pettenò 
Packit dd8086
  Thomas Schmitt
Packit dd8086
Packit dd8086
  This program is free software: you can redistribute it and/or modify
Packit dd8086
  it under the terms of the GNU General Public License as published by
Packit dd8086
  the Free Software Foundation, either version 3 of the License, or
Packit dd8086
  (at your option) any later version.
Packit dd8086
Packit dd8086
  This program is distributed in the hope that it will be useful,
Packit dd8086
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit dd8086
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit dd8086
  GNU General Public License for more details.
Packit dd8086
Packit dd8086
  You should have received a copy of the GNU General Public License
Packit dd8086
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit dd8086
*/
Packit dd8086
/*
Packit dd8086
  POSIX realpath if that's around, and something like it if not.
Packit dd8086
Packit dd8086
  To compile as a standalone program:
Packit dd8086
  gcc -Wall -g -I../.. -DHAVE_CONFIG_H -DSTANDALONE -o realpath realpath.c
Packit dd8086
*/
Packit dd8086
/*
Packit dd8086
  Make sure we handle:
Packit dd8086
  - resolve relative links like  /dev/cdrom -> sr2
Packit dd8086
  - abort on cyclic linking like /dev/cdrom -> /dev/cdrom
Packit dd8086
*/
Packit dd8086
Packit dd8086
#ifdef HAVE_CONFIG_H
Packit dd8086
# include "config.h"
Packit dd8086
# define __CDIO_CONFIG_H__ 1
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <ctype.h>
Packit dd8086
Packit dd8086
#ifdef HAVE_STDLIB_H
Packit dd8086
# include <stdlib.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_STDIO_H
Packit dd8086
# include <stdio.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_STRING_H
Packit dd8086
# include <string.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_UNISTD_H /* readlink */
Packit dd8086
# include <unistd.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_INTTYPES_H
Packit dd8086
# include "inttypes.h"
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_LIMITS_H
Packit dd8086
# include <limits.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifndef PATH_MAX
Packit dd8086
#define PATH_MAX 4096
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <cdio/util.h>
Packit dd8086
Packit dd8086
/*!  cdio_realpath() same as POSIX.1-2001 realpath if that's
Packit dd8086
around. If not we do poor-man's simulation of that behavior.  */
Packit dd8086
char *cdio_realpath (const char *psz_src_path, char *psz_resolved_path) {
Packit dd8086
Packit dd8086
#ifdef HAVE_REALPATH
Packit dd8086
  psz_resolved_path = realpath(psz_src_path, psz_resolved_path);
Packit dd8086
Packit dd8086
#elif defined(HAVE_READLINK)
Packit dd8086
  char tmp_src[PATH_MAX+1];
Packit dd8086
  char tmp_dst[PATH_MAX+1];
Packit dd8086
  char *p_adr;
Packit dd8086
  int i, len;
Packit dd8086
  const int loop_limit = 100;
Packit dd8086
Packit dd8086
  strcpy(tmp_src, psz_src_path);
Packit dd8086
Packit dd8086
  /* FIXME: 
Packit dd8086
     remove loop and change with stat before and after readlink 
Packit dd8086
     which looks direct symlink. Rely on errno to figure out other
Packit dd8086
     non-existent or looped symlinks. 
Packit dd8086
  */
Packit dd8086
  for(i = 0; i < loop_limit; i++) {
Packit dd8086
    len = readlink(tmp_src, tmp_dst, PATH_MAX);
Packit dd8086
    if (-1 == len) {
Packit dd8086
	/* Right now we expect a "not symlink" error. However after
Packit dd8086
	   we put in the stat() suggested above, there won't be a symlink
Packit dd8086
	   error and we should start reporting what the failure is.
Packit dd8086
	*/
Packit dd8086
	break;
Packit dd8086
    } else {
Packit dd8086
	tmp_dst[len] = '\0';
Packit dd8086
	if (tmp_dst[0] != '/') {
Packit dd8086
	    /* Take care of relative link like  /dev/cdrom -> sr2 */
Packit dd8086
	    p_adr = strrchr(tmp_src, '/');
Packit dd8086
	    if (p_adr != NULL) {
Packit dd8086
		strncpy(p_adr + 1, tmp_dst, PATH_MAX - (p_adr + 1 - tmp_src));
Packit dd8086
	    } else {
Packit dd8086
		strncpy(tmp_src, tmp_dst, PATH_MAX);
Packit dd8086
	    }
Packit dd8086
	} else {
Packit dd8086
	    strncpy(tmp_src, tmp_dst, PATH_MAX);
Packit dd8086
	}
Packit dd8086
	tmp_src[PATH_MAX - 1] = 0; /* strncpy() does not always set a 0 */
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
  strncpy(psz_resolved_path, tmp_src, PATH_MAX);
Packit dd8086
#else
Packit dd8086
  strncpy(psz_resolved_path, psz_src_path, PATH_MAX);
Packit dd8086
#endif
Packit dd8086
Packit dd8086
  return psz_resolved_path;
Packit dd8086
  
Packit dd8086
}
Packit dd8086
Packit dd8086
#ifdef STANDALONE
Packit dd8086
int main(int argc, char **argv)
Packit dd8086
{
Packit dd8086
  int i;
Packit dd8086
  char dest[PATH_MAX];
Packit dd8086
Packit dd8086
  if (argc < 2) {
Packit dd8086
    fprintf(stderr, "Usage: %s  path [path ...]\n", argv[0]);
Packit dd8086
    fprintf(stderr,
Packit dd8086
     "       Resolve symbolic links\n");
Packit dd8086
    exit(1);
Packit dd8086
  }
Packit dd8086
  for (i= 1; i < argc; i++) {
Packit dd8086
    dest[0] = 0;
Packit dd8086
    cdio_realpath (argv[i], dest);
Packit dd8086
    printf("%s -> %s\n", argv[i], dest);
Packit dd8086
  }
Packit dd8086
  exit(0);
Packit dd8086
}
Packit dd8086
#endif