Date: Fri, 28 May 2004 22:17:05 +0200 From: Cyrille Lefevre <cyrille.lefevre@laposte.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/67308: ready to import bootstrap_cmds/relpath from Darwin Message-ID: <20040528201705.GA83895@gits.dyndns.org> Resent-Message-ID: <200405282020.i4SKKNuT009998@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 67308 >Category: bin >Synopsis: ready to import bootstrap_cmds/relpath from Darwin >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri May 28 13:20:23 PDT 2004 >Closed-Date: >Last-Modified: >Originator: Cyrille Lefevre >Release: FreeBSD 5.2-CURRENT i386 >Organization: ACME >Environment: System: FreeBSD gits 5.2-CURRENT FreeBSD 5.2-CURRENT #28: Thu May 13 00:19:50 CEST 2004 root@gits:/disk3/freebsd/current/obj/disk3/freebsd/current/src/sys/CUSTOM i386 >Description: Usage: relpath [-d DIR] START_PATH END_PATH >How-To-Repeat: $ relpath /usr/local/etc/rc.d /tmp ../../../../tmp $ relpath -d /usr /usr/local/etc/rc.d /tmp /tmp >Fix: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # usr.bin/relpath/Makefile # usr.bin/relpath/relpath.c # echo x - usr.bin/relpath/Makefile sed 's/^X//' >usr.bin/relpath/Makefile << 'END-of-usr.bin/relpath/Makefile' X# $FreeBSD$ X XPROG= relpath XWARNS?= 6 XNO_MAN= yes X X.include <bsd.prog.mk> END-of-usr.bin/relpath/Makefile echo x - usr.bin/relpath/relpath.c sed 's/^X//' >usr.bin/relpath/relpath.c << 'END-of-usr.bin/relpath/relpath.c' X/* X * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. X * X * @APPLE_LICENSE_HEADER_START@ X * X * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. X * X * This file contains Original Code and/or Modifications of Original Code X * as defined in and that are subject to the Apple Public Source License X * Version 2.0 (the 'License'). You may not use this file except in X * compliance with the License. Please obtain a copy of the License at X * http://www.opensource.apple.com/apsl/ and read it before using this X * file. X * X * The Original Code and all software distributed under the License are X * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER X * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, X * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, X * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. X * Please see the License for the specific language governing rights and X * limitations under the License. X * X * @APPLE_LICENSE_HEADER_END@ X */ X/* X * relpath [-d DIR] START_DIR END_PATH X * X * Find a relative path from START_DIR to END_PATH. X * Prints the relative path on standard out. X * X * If -d DIR, then only emit a relative path if both X * START_DIR and END_PATH are sub-directories of DIR; X * otherwise, emit an absolute path to END_PATH. X */ X/* X ********************************************************************** X * HISTORY X * 27-May-04 Cyrille Lefevre for FreeBSD X * Make it compile under FreeBSD. modifications are __FreeBSD__ #ifdef'ed. X ********************************************************************** X */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/param.h> X#ifdef __FreeBSD__ X#include <stdlib.h> X#include <string.h> X#include <unistd.h> X#define symlink _symlink X#else X#include <strings.h> X#include <libc.h> X#endif X Xstatic int is_prefix(const char *path1, const char *path2); Xstatic char *abspath(const char *opath, char *absbuf); X Xconst char *progname; X X#ifdef __FreeBSD__ Xint X#else Xvoid X#endif Xmain(int argc, const char * const *argv) X{ X const char *arg; X const char *base_dir = NULL; X char start_path[MAXPATHLEN+1]; X char end_path[MAXPATHLEN+1]; X char base_path[MAXPATHLEN+1]; X struct stat st; X int i; X int last_elem; X int prev_path; X X unsetenv("PWD"); X X progname = (arg = rindex(*argv, '/')) != NULL ? arg + 1 : *argv; X argc -= 1; argv += 1; X X for (; argc > 1 && **argv == '-'; argv += 1, argc -= 1) { X X arg = &(*argv)[1]; X do { X switch (*arg) { X case 'd': X argc -= 1; argv += 1; X if (argc <= 0) { X fprintf(stderr, "%s: -d takes " X "directory name\n", progname); X exit(1); X } X base_dir = *argv; X break; X default: X fprintf(stderr, "%s: Illegal flag: %c\n", X progname, *arg); X exit(1); X } X } while (*++arg); X } X if (argc < 2) { X fprintf(stderr, "Usage: %s [-d DIR] START_PATH END_PATH\n", X progname); X exit(1); X } X (void) abspath(argv[0], start_path); X (void) abspath(argv[1], end_path); X if (base_dir) { X (void) abspath(base_dir, base_path); X if (!is_prefix(base_path, start_path) || X !is_prefix(base_path, end_path)) { X printf("%s\n", end_path); X exit(0); X } X if (stat(base_path, &st) < 0) { X fprintf(stderr, "%s: ", progname); X perror(base_path); X exit(1); X } X if ((st.st_mode & S_IFMT) != S_IFDIR) { X fprintf(stderr, "%s: -d DIR must be directory\n", X progname); X exit(1); X } X } X if (stat(start_path, &st) < 0) { X fprintf(stderr, "%s: ", progname); X perror(start_path); X exit(1); X } X if ((st.st_mode & S_IFMT) != S_IFDIR) { X fprintf(stderr, "%s: START_PATH must be directory\n", X progname); X exit(1); X } X if (start_path[strlen(start_path) - 1] != '/') X strcat(start_path, "/"); X X if (stat(end_path, &st) < 0) { X fprintf(stderr, "%s: ", progname); X perror(end_path); X exit(1); X } X if ((st.st_mode & S_IFMT) == S_IFDIR X && end_path[strlen(end_path) - 1] != '/') X strcat(end_path, "/"); X X /* strip common prefix */ X i = 0; X last_elem = 0; X while (start_path[i] && start_path[i] == end_path[i]) { X if (start_path[i] == '/') X last_elem = i + 1; X i += 1; X } X prev_path = 0; X for (i = last_elem; start_path[i]; i += 1) { X if (start_path[i] == '/') { X if (prev_path) X putchar('/'); X printf("%s", ".."); X prev_path = 1; X } X } X if (end_path[last_elem]) { X if (prev_path) X putchar('/'); X prev_path = 1; X while (end_path[strlen(end_path) - 1] == '/') X end_path[strlen(end_path) - 1] = '\0'; X printf("%s", &end_path[last_elem]); X } X if (! prev_path) X putchar('.'); X putchar('\n'); X#ifdef __FreeBSD__ X return(0); X#else X exit(0); X#endif X} X Xstatic int Xis_prefix(const char *path1, const char *path2) X{ X while (*path1 && *path1 == *path2) { X path1 += 1; X path2 += 1; X } X return (*path1 == '\0' && (*path2 == '/' || *path2 == '\0')); X} X Xstatic char * Xabspath(const char *opath, char *absbuf) X{ X struct stat st; X char curdir[MAXPATHLEN+1]; X char symlink[MAXPATHLEN+1]; X char path[MAXPATHLEN+1]; X char file[MAXPATHLEN+1]; X char *cp; X int cc; X X strcpy(path, opath); X /* X * resolve last element of path until we know it's not X * a symbolic link X */ X while (lstat(path, &st) >= 0 X && (st.st_mode & S_IFMT) == S_IFLNK X && (cc = readlink(path, symlink, sizeof(symlink)-1)) > 0) { X symlink[cc] = '\0'; X if ((cp = rindex(path, '/')) != NULL && symlink[0] != '/') X *++cp = '\0'; X else X path[0] = '\0'; X strcat(path, symlink); X } X /* X * We cheat a little bit here and let getwd() do the X * dirty work of resolving everything before the last X * element of the path X */ X if (getwd(curdir) == NULL) { X fprintf(stderr, "%s: %s\n", progname, curdir); X exit(1); X } X if ((st.st_mode & S_IFMT) == S_IFDIR) { X if (chdir(path) < 0) { X fprintf(stderr, "%s: ", progname); X perror(path); X exit(1); X } X if (getwd(absbuf) == NULL) { X fprintf(stderr, "%s: %s\n", progname, absbuf); X exit(1); X } X if (chdir(curdir) < 0) { X fprintf(stderr, "%s: ", progname); X perror(path); X exit(1); X } X return absbuf; X } X if ((cp = rindex(path, '/')) == NULL) { X /* X * last element of path is only element and it X * now not a symbolic link, so we're done X */ X strcpy(absbuf, curdir); X if (absbuf[strlen(absbuf) - 1] != '/') X strcat(absbuf, "/"); X return strcat(absbuf, path); X } X *cp++ = 0; X strcpy(file, cp); /* save last element */ X X if (chdir(path) < 0) { X fprintf(stderr, "%s: ", progname); X perror(path); X exit(1); X } X if (getwd(absbuf) == NULL) { X fprintf(stderr, "%s: %s\n", progname, absbuf); X exit(1); X } X X if (chdir(curdir) < 0) { X fprintf(stderr, "%s: ", progname); X perror(path); X exit(1); X } X if (absbuf[strlen(absbuf)-1] != '/') X strcat(absbuf, "/"); X return strcat(absbuf, file); X} END-of-usr.bin/relpath/relpath.c exit >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040528201705.GA83895>