From owner-freebsd-bugs@FreeBSD.ORG Fri May 28 13:20:26 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5CF6116A4CE for ; Fri, 28 May 2004 13:20:26 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4D8AE43D2D for ; Fri, 28 May 2004 13:20:26 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i4SKKN7S009999 for ; Fri, 28 May 2004 13:20:23 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i4SKKNuT009998; Fri, 28 May 2004 13:20:23 -0700 (PDT) (envelope-from gnats) Resent-Date: Fri, 28 May 2004 13:20:23 -0700 (PDT) Resent-Message-Id: <200405282020.i4SKKNuT009998@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Cyrille Lefevre Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9546616A4CE for ; Fri, 28 May 2004 13:18:07 -0700 (PDT) Received: from ioskeha.hittite.isp.9tel.net (ioskeha.hittite.isp.9tel.net [62.62.156.27]) by mx1.FreeBSD.org (Postfix) with ESMTP id E29C143D3F for ; Fri, 28 May 2004 13:18:02 -0700 (PDT) (envelope-from cyrille.lefevre@laposte.net) Received: from mail.gits.dyndns.org (unknown [80.119.167.76]) by ioskeha.hittite.isp.9tel.net (Postfix) with ESMTP id 1E04B17B77F for ; Fri, 28 May 2004 22:18:46 +0200 (CEST) Received: from gits.gits.fr.invalid (IDENT:k6wn7o04m9mf81iz@localhost [127.0.0.1])i4SKHCkG022539 for ; Fri, 28 May 2004 22:17:28 +0200 (CEST) (envelope-from cyrille.lefevre@laposte.net) Received: by gits.gits.fr.invalid (tmda-sendmail, from uid 0); Fri, 28 May 2004 22:17:12 +0200 (CEST) Message-Id: <20040528201705.GA83895@gits.dyndns.org> Date: Fri, 28 May 2004 22:17:05 +0200 From: Cyrille Lefevre To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/67308: ready to import bootstrap_cmds/relpath from Darwin X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Cyrille Lefevre List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 May 2004 20:20:26 -0000 >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 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 X#include X#include X#include X#ifdef __FreeBSD__ X#include X#include X#include X#define symlink _symlink X#else X#include X#include 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: