From - Tue Feb 11 23:56:02 1997 Path: news.unizar.es!news.rediris.es!news.belnet.be!news-penn.gsl.net!news.gsl.net!news.RoSprint.net!ekaterinburg.rosprint.ru!news.e-burg.ru!demos!news-out.communique.net!mr.net!netnews.com!howland.erols.net!rill.news.pipex.net!pipex!warwick!not-for-mail From: Rob McMahon Newsgroups: comp.unix.solaris Subject: Re: How to get true path? Date: 6 Feb 1997 12:44:46 -0000 Organization: University of Warwick, Coventry, UK Lines: 192 Sender: cudcv@csv.warwick.ac.uk Distribution: inet Message-ID: References: <5cbfu4$316@aslan.positron.com> <5ctb85$c4e@engnews2.Eng.Sun.COM> NNTP-Posting-Host: pansy-fddi.csv.warwick.ac.uk Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Newsreader: Gnus v5.2.25/XEmacs 19.14 Rob McMahon writes: > How about recovering files as an example. `nwrecover' for example needs the > true, fundamental path on the server. I had to write a wrapper around this > to try to work that out. Other schemes will be dumping the ufs filesystem, > and you will need to know which dump to look at. Which reminds me. Here's the code I knocked together to do just this. Use is `rpath [warped_path]', it prints the true path on stdout. The path must be absolute, and defaults to the current directory. (This also has a bug fixed from the previous version I posted.) ------------------------------------------------------------------------------ #include #include #include #include #include #include #include #include #include extern int errno; static void fatal(char *fmt, ...); static void *xalloc(void *p, size_t len); static size_t path_max(const char *path); char *progname; int debug; int main(int argc, char **argv) { long maxpath; char old_char; char *p, *newp; char *path; char *working_path = 0, *new_path = 0; FILE *mntfp; struct mnttab mnttab, mntref; struct stat stbuf; int c; extern int optind; if ((progname = strrchr(argv[0], '/')) == 0) progname = argv[0]; else progname++; while ((c = getopt(argc, argv, "d")) != EOF) { switch (c) { case 'd': debug++; break; default: fatal("Usage: %s [-d] [path]", progname); } } if ((mntfp = fopen(MNTTAB, "r")) == 0) { fatal("Couldn't open %s: %s", MNTTAB, strerror(errno)); } if (optind < argc) { path = argv[optind]; maxpath = path_max(path); } else { maxpath = path_max("."); path = xalloc(0, maxpath + 1); if (getcwd(path, maxpath) == 0) fatal("Couldn't get current directory: %s", strerror(errno)); } if (stat(path, &stbuf) != 0) { fatal("Couldn't stat %s: %s", path, strerror(errno)); } if ((stbuf.st_mode & S_IFMT) != S_IFDIR) { fatal("%s: Not a directory", path); } start_again: /* Come back here if we hit a loopback mount */ working_path = xalloc(working_path, maxpath + 1); strncpy(working_path, path, maxpath); working_path[maxpath] = '\0'; memset((void *)&mntref, 0, sizeof(mntref)); mntref.mnt_mountp = working_path; if (debug) fprintf(stderr, "Looking for %s\n", working_path); /* Work back through the path until we hit a mount point */ p = working_path + strlen(working_path); do { int res; old_char = *p; *p = '\0'; rewind(mntfp); do { res = getmntany(mntfp, &mnttab, &mntref); if (debug && res == 0) fprintf(stderr, "%s\t%s\t%s\t%s\t%s\n", mnttab.mnt_special, mnttab.mnt_mountp, mnttab.mnt_fstype, mnttab.mnt_mntopts, mnttab.mnt_time); } while (res == 0 && hasmntopt(&mnttab, "ignore") != NULL); if (res == 0) { if (strcmp(mnttab.mnt_fstype, "lofs") == 0) { /* go round again */ maxpath = path_max(mnttab.mnt_special); new_path = xalloc(new_path, maxpath + 1); new_path[maxpath] = '\0'; strncpy(new_path, mnttab.mnt_special, maxpath); if (p[1] != '\0') { strncat(new_path, "/", maxpath - strlen(new_path)); strncat(new_path, p + 1, maxpath - strlen(new_path)); } path = new_path; goto start_again; } else if (strncmp(mnttab.mnt_special, "/dev/", 5) == 0) { /* Bit of a cheat, I suppose, but this is going to be local */ printf("%s", mnttab.mnt_mountp); if (old_char != '\0') printf("%c%s", old_char, p + 1); putchar('\n'); *p = old_char; break; } else { /* This is a remote mount, presumably, that's as far as we get */ printf("%s", mnttab.mnt_special); if (old_char != '\0') printf("%c%s", old_char, p + 1); putchar('\n'); *p = old_char; break; } printf("%s\n", working_path); break; } newp = strrchr(working_path, '/'); *p = old_char; /* XXX This will loop if there's no / in mnttab. There better had be. */ if ((p = newp) == working_path) p++; } while (p); exit(0); } static void fatal(char *fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "%s: ", progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); exit(1); } static void * xalloc(void *p, size_t len) { if (p) p = realloc(p, len); else p = malloc(len); if (p == 0) fatal("Out of memory"); return p; } static size_t path_max(const char *path) { return PATH_MAX; #if 0 /* XXX doesn't appear to work ... */ if ((maxpath = pathconf(path, _PC_PATH_MAX)) < 0) { maxpath = _POSIX_PATH_MAX; } #endif } ------------------------------------------------------------------------------ -- UUCP: ...!mcsun!uknet!warwick!cudcv PHONE: +44 1203 523037 INET: cudcv@csv.warwick.ac.uk Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England