/* * $Id: mac.c 443 2006-05-30 04:37:13Z darren $ * * Copyright (c) 2001, Maarten L. Hekkelman * * Author: Maarten L. Hekkelman * http://www.hekkelman.com * * This source code is released for free distribution under the terms of the * GNU General Public License. It is provided on an as-is basis and no * responsibility is accepted for its failure to perform as expected. * * This module contains support functions for Exuberant Ctags on Macintosh. */ /* * INCLUDE FILES */ #include "general.h" #include #include #include #include #include /* * FUNCTION DEFINITIONS */ static int get_path(const char* in_unix_path, unsigned char* out_mac_path) { int l = strlen(in_unix_path); int result = 0; if (l > 254) result = -1; else { const char* s = in_unix_path; char *d = (char*)out_mac_path + 1; if (*s != '/') *d++ = ':'; else ++s; while (*s) { if (s[0] == '.' && s[1] == '.' && s[2] == '/') { s += 3; *d++ = ':'; } else if (s[0] == '.' && s[1] == '/') s += 2; else if (s[0] == '/') { *d++ = ':'; ++s; while (*s == '/') ++s; } else *d++ = *s++; } out_mac_path[0] = (d - (char*)out_mac_path) - 1; } return result; } DIR *opendir(const char *dirname) { DIR* dirp = (DIR*)calloc(1, sizeof(DIR)); if (dirp != NULL) { OSErr err; Str255 s; CInfoPBRec pb = { 0 }; if (strcmp(dirname, ".")) { get_path(dirname, s); pb.hFileInfo.ioNamePtr = s; } else pb.hFileInfo.ioNamePtr = NULL; err = PBGetCatInfoSync(&pb); if (err != noErr || (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0) { free(dirp); dirp = NULL; } else { dirp->file.vRefNum = pb.hFileInfo.ioVRefNum; dirp->file.parID = pb.hFileInfo.ioDirID; dirp->file.name[0] = '\0'; dirp->index = 1; } } return dirp; } struct dirent *readdir(DIR *dirp) { if (dirp) { CInfoPBRec pb = { 0 }; pb.hFileInfo.ioVRefNum = dirp->file.vRefNum; pb.hFileInfo.ioDirID = dirp->file.parID; pb.hFileInfo.ioFDirIndex = dirp->index++; pb.hFileInfo.ioNamePtr = dirp->file.name; if (PBGetCatInfoSync(&pb) != noErr) return NULL; memcpy(dirp->ent.d_name, dirp->file.name + 1, dirp->file.name[0]); dirp->ent.d_name[dirp->file.name[0]] = 0; return &dirp->ent; } return NULL; } int closedir(DIR *dirp) { if (dirp) free(dirp); return 0; } void rewinddir(DIR *dirp) { if (dirp) dirp->index = 1; } int mstat(const char* file, struct stat* st) { CInfoPBRec pb; unsigned char path[256]; int result = 0; memset(&pb, 0, sizeof(CInfoPBRec)); if (strcmp(file, ".") == 0) { memset(st, 0, sizeof(struct stat)); st->st_mode = S_IFDIR; st->st_ino = -1; } else { result = get_path(file, path); if (result == 0) { pb.hFileInfo.ioNamePtr = path; if (PBGetCatInfoSync(&pb) != noErr) result = -1; else { memset(st, 0, sizeof(struct stat)); if (pb.hFileInfo.ioFlAttrib & ioDirMask) st->st_mode = S_IFDIR; else st->st_mode = S_IFREG; st->st_ino = pb.hFileInfo.ioFlStBlk; st->st_dev = pb.hFileInfo.ioVRefNum; st->st_nlink = 1; st->st_size = pb.hFileInfo.ioFlLgLen; st->st_atime = pb.hFileInfo.ioFlMdDat; st->st_mtime = pb.hFileInfo.ioFlMdDat; st->st_ctime = pb.hFileInfo.ioFlCrDat; } } } return result; } #undef fopen FILE* mfopen(const char* file, const char* mode) { unsigned char path[256]; if (get_path(file, path) == 0) { int l = path[0]; memmove(path, path + 1, l); path[l] = 0; return fopen((char*)path, mode); } else return NULL; } char* getcwd(char* out_path, int out_path_len) { OSErr err = noErr; CInfoPBRec pb; FSSpec cwd; if (out_path == NULL) { if (out_path_len < PATH_MAX) out_path_len = PATH_MAX; out_path = (char*)malloc(out_path_len); } err = FSMakeFSSpec(0, 0, "\p:", &cwd); if (cwd.parID == fsRtParID) { *out_path = '/'; memcpy(out_path + 1, cwd.name + 1, cwd.name[0]); out_path[1 + cwd.name[0]] = 0; } else { /* The object isn't a volume */ /* Is the object a file or a directory? */ char t[PATH_MAX]; char* s; s = t + PATH_MAX - cwd.name[0] - 1; memcpy(s, cwd.name + 1, cwd.name[0]); s[cwd.name[0]] = 0; /* Get the ancestor directory names */ pb.dirInfo.ioNamePtr = cwd.name; pb.dirInfo.ioVRefNum = cwd.vRefNum; pb.dirInfo.ioDrParID = cwd.parID; do /* loop until we have an error or find the root directory */ { pb.dirInfo.ioFDirIndex = -1; pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; err = PBGetCatInfoSync(&pb); if ( err == noErr ) { *--s = '/'; s -= cwd.name[0]; memcpy(s, cwd.name + 1, cwd.name[0]); } } while (err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID && s > t + 1); if (s > t + 1) { *--s = '/'; strcpy(out_path, s); } else strcpy(out_path, "."); } return out_path; } /* vi:set tabstop=4 shiftwidth=4: */