|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 7058 (0x1b92) Types: TextFile Names: »direct.c«
└─⟦8648bda34⟧ Bits:30007244 EUUGD5_II: X11R5 └─⟦87c3ac0e0⟧ »./contrib-3/contrib-3.00« └─⟦de8ce1454⟧ └─⟦this⟧ »contrib/lib/iv/src/bin/iclass/direct.c«
/* * Copyright (c) 1989 Stanford University * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Stanford not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Stanford makes no representations about * the suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Directory object implementation. */ #include "direct.h" #include "globals.h" #include <OS/directory.h> #include <OS/leave-scope.h> #include <stddef.h> #include <osfcn.h> #include <pwd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #define SysDir _lib_os(Directory) #define SysDirInfo _lib_os(DirectoryInfo) class DirectoryRep { private: friend class Directory; SysDir* dir; }; static const int MAX_PATH_LENGTH = 256; /*****************************************************************************/ Directory::Directory (const char* name) { rep_ = new DirectoryRep; rep_->dir = nil; LoadDirectory(name); } Directory::~Directory () { delete rep_->dir; delete rep_; } const char* Directory::RealPath (const char* path) { const char* realpath; if (*path == '\0') { realpath = "./"; } else { realpath = InterpTilde(InterpSlashSlash(path)); } return realpath; } boolean Directory::LoadDirectory (const char* name) { char buf[MAX_PATH_LENGTH+2]; const char* path = buf; strcpy(buf, ValidDirectories(RealPath(name))); return Reset(buf); } int Directory::Index (const char* name) { return rep_->dir == nil ? -1 : rep_->dir->index(name); } boolean Directory::Reset (char* path) { SysDirInfo* info = SysDir::open(path); if (info != nil) { delete rep_->dir; rep_->dir = new SysDir(info); return true; } return false; } boolean Directory::IsADirectory (const char* path) { struct stat filestats; stat(path, &filestats); return filestats.st_mode & S_IFDIR; } int Directory::Count() { return rep_->dir == nil ? 0 : rep_->dir->count(); } const char* Directory::File(int index) { return rep_->dir == nil ? nil : rep_->dir->name(index); } const char* Directory::Home (const char* name) { struct passwd* pw = (name == nil) ? getpwuid(getuid()) : getpwnam(name); return (pw == nil) ? nil : pw->pw_dir; } inline boolean DotSlash (const char* path) { return path[0] != '\0' && path[0] == '.' && (path[1] == '/' || path[1] == '\0'); } inline boolean DotDotSlash (const char* path) { return path[0] != '\0' && path[1] != '\0' && path[0] == '.' && path[1] == '.' && (path[2] == '/' || path[2] == '\0'); } const char* Directory::Normalize (const char* path) { static char newpath[MAX_PATH_LENGTH+1]; const char* buf; buf = InterpSlashSlash(path); buf = ElimDot(buf); buf = ElimDotDot(buf); buf = InterpTilde(buf); if (*buf == '\0') { strcpy(newpath, "./"); } else if (!DotSlash(buf) && !DotDotSlash(buf) && *buf != '/') { strcpy(newpath, "./"); strcat(newpath, buf); } else { strcpy(newpath, buf); } if (IsADirectory(newpath) && newpath[strlen(newpath)-1] != '/') { strcat(newpath, "/"); } return newpath; } const char* Directory::ValidDirectories (const char* path) { static char buf[MAX_PATH_LENGTH+1]; strcpy(buf, path); int i = strlen(path); while (!IsADirectory(RealPath(buf)) && i >= 0) { for (--i; buf[i] != '/' && i >= 0; --i); buf[i+1] = '\0'; } return buf; } const char* Directory::InterpSlashSlash (const char* path) { for (int i = strlen(path)-1; i > 0; --i) { if (path[i] == '/' && path[i-1] == '/') { return &path[i]; } } return path; } const char* Directory::ElimDot (const char* path) { static char newpath[MAX_PATH_LENGTH+1]; const char* src; char* dest = newpath; for (src = path; src < &path[strlen(path)]; ++src) { if (!DotSlash(src)) { *dest++ = *src; } else if (*(dest-1) == '/') { ++src; } else { *dest++ = *src; } } *dest = '\0'; return newpath; } static boolean CollapsedDotDotSlash (const char* path, const char*& start) { if (path == start || *(start-1) != '/') { return false; } else if (path == start-1 && *path == '/') { return true; } else if (path == start-2) { // NB: won't handle '//' right start = path; return *start != '.'; } else if (path < start-2 && !DotDotSlash(start-3)) { for (start -= 2; path <= start; --start) { if (*start == '/') { ++start; return true; } } start = path; return true; } return false; } const char* Directory::ElimDotDot (const char* path) { static char newpath[MAX_PATH_LENGTH+1]; const char* src; char* dest = newpath; for (src = path; src < &path[strlen(path)]; ++src) { if (DotDotSlash(src) && CollapsedDotDotSlash(newpath, dest)) { src += 2; } else { *dest++ = *src; } } *dest = '\0'; return newpath; } const char* Directory::InterpTilde (const char* path) { static char realpath[MAX_PATH_LENGTH+1]; const char* beg = strrchr(path, '~'); boolean validTilde = beg != nil && (beg == path || *(beg-1) == '/'); if (validTilde) { const char* end = strchr(beg, '/'); int length = (end == nil) ? strlen(beg) : end - beg; const char* expandedTilde = ExpandTilde(beg, length); if (expandedTilde == nil) { validTilde = false; } else { strcpy(realpath, expandedTilde); if (end != nil) { strcat(realpath, end); } } } return validTilde ? realpath : path; } const char* Directory::ExpandTilde (const char* tildeName, int length) { const char* name = nil; if (length > 1) { static char buf[MAX_PATH_LENGTH+1]; strncpy(buf, tildeName+1, length-1); buf[length-1] = '\0'; name = buf; } return Home(name); }