274 lines
4.9 KiB
C
274 lines
4.9 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) 2001, Maarten L. Hekkelman
|
|
*
|
|
* Author: Maarten L. Hekkelman <maarten@hekkelman.com>
|
|
* 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 <Files.h>
|
|
#include <TextUtils.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
/*
|
|
* 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: */
|