📄 routines.c
字号:
file.isExecutable = (boolean) ((status.st_mode &
(S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
file.isSetuid = (boolean) ((status.st_mode & S_ISUID) != 0);
file.size = status.st_size;
}
}
}
return &file;
}
extern boolean doesFileExist (const char *const fileName)
{
fileStatus *status = eStat (fileName);
return status->exists;
}
extern boolean isRecursiveLink (const char* const dirName)
{
boolean result = FALSE;
fileStatus *status = eStat (dirName);
if (status->isSymbolicLink)
{
char* const path = absoluteFilename (dirName);
while (path [strlen (path) - 1] == PATH_SEPARATOR)
path [strlen (path) - 1] = '\0';
while (! result && strlen (path) > (size_t) 1)
{
char *const separator = strrchr (path, PATH_SEPARATOR);
if (separator == NULL)
break;
else if (separator == path) /* backed up to root directory */
*(separator + 1) = '\0';
else
*separator = '\0';
result = isSameFile (path, dirName);
}
eFree (path);
}
return result;
}
#ifndef HAVE_FGETPOS
extern int fgetpos (FILE *stream, fpos_t *pos)
{
int result = 0;
*pos = ftell (stream);
if (*pos == -1L)
result = -1;
return result;
}
extern int fsetpos (FILE *stream, fpos_t const *pos)
{
return fseek (stream, *pos, SEEK_SET);
}
#endif
/*
* Pathname manipulation (O/S dependent!!!)
*/
static boolean isPathSeparator (const int c)
{
boolean result;
#if defined (MSDOS_STYLE_PATH) || defined (VMS)
result = (boolean) (strchr (PathDelimiters, c) != NULL);
#else
result = (boolean) (c == PATH_SEPARATOR);
#endif
return result;
}
#if ! defined (HAVE_STAT_ST_INO)
static void canonicalizePath (char *const path __unused__)
{
#if defined (MSDOS_STYLE_PATH)
char *p;
for (p = path ; *p != '\0' ; ++p)
if (isPathSeparator (*p) && *p != ':')
*p = PATH_SEPARATOR;
#endif
}
#endif
extern boolean isSameFile (const char *const name1, const char *const name2)
{
boolean result = FALSE;
#if defined (HAVE_STAT_ST_INO)
struct stat stat1, stat2;
if (stat (name1, &stat1) == 0 && stat (name2, &stat2) == 0)
result = (boolean) (stat1.st_ino == stat2.st_ino);
#else
{
char *const n1 = absoluteFilename (name1);
char *const n2 = absoluteFilename (name2);
canonicalizePath (n1);
canonicalizePath (n2);
# if defined (CASE_INSENSITIVE_FILENAMES)
result = (boolean) (strcasecmp (n1, n2) == 0);
#else
result = (boolean) (strcmp (n1, n2) == 0);
#endif
free (n1);
free (n2);
}
#endif
return result;
}
extern const char *baseFilename (const char *const filePath)
{
#if defined (MSDOS_STYLE_PATH) || defined (VMS)
const char *tail = NULL;
unsigned int i;
/* Find whichever of the path delimiters is last.
*/
for (i = 0 ; i < strlen (PathDelimiters) ; ++i)
{
const char *sep = strrchr (filePath, PathDelimiters [i]);
if (sep > tail)
tail = sep;
}
#else
const char *tail = strrchr (filePath, PATH_SEPARATOR);
#endif
if (tail == NULL)
tail = filePath;
else
++tail; /* step past last delimiter */
#ifdef VAXC
{
/* remove version number from filename */
char *p = strrchr ((char *) tail, ';');
if (p != NULL)
*p = '\0';
}
#endif
return tail;
}
extern const char *fileExtension (const char *const fileName)
{
const char *extension;
const char *pDelimiter = NULL;
const char *const base = baseFilename (fileName);
#ifdef QDOS
pDelimiter = strrchr (base, '_');
#endif
if (pDelimiter == NULL)
pDelimiter = strrchr (base, '.');
if (pDelimiter == NULL)
extension = "";
else
extension = pDelimiter + 1; /* skip to first char of extension */
return extension;
}
extern boolean isAbsolutePath (const char *const path)
{
boolean result = FALSE;
#if defined (MSDOS_STYLE_PATH)
if (isPathSeparator (path [0]))
result = TRUE;
else if (isalpha (path [0]) && path [1] == ':')
{
if (isPathSeparator (path [2]))
result = TRUE;
else
/* We don't support non-absolute file names with a drive
* letter, like `d:NAME' (it's too much hassle).
*/
error (FATAL,
"%s: relative file names with drive letters not supported",
path);
}
#elif defined (VMS)
result = (boolean) (strchr (path, ':') != NULL);
#else
result = isPathSeparator (path [0]);
#endif
return result;
}
extern vString *combinePathAndFile (
const char *const path, const char *const file)
{
vString *const filePath = vStringNew ();
#ifdef VMS
const char *const directoryId = strstr (file, ".DIR;1");
if (directoryId == NULL)
{
const char *const versionId = strchr (file, ';');
vStringCopyS (filePath, path);
if (versionId == NULL)
vStringCatS (filePath, file);
else
vStringNCatS (filePath, file, versionId - file);
vStringCopyToLower (filePath, filePath);
}
else
{
/* File really is a directory; append it to the path.
* Gotcha: doesn't work with logical names.
*/
vStringNCopyS (filePath, path, strlen (path) - 1);
vStringPut (filePath, '.');
vStringNCatS (filePath, file, directoryId - file);
if (strchr (path, '[') != NULL)
vStringPut (filePath, ']');
else
vStringPut (filePath, '>');
vStringTerminate (filePath);
}
#else
const int lastChar = path [strlen (path) - 1];
boolean terminated = isPathSeparator (lastChar);
vStringCopyS (filePath, path);
if (! terminated)
{
vStringPut (filePath, OUTPUT_PATH_SEPARATOR);
vStringTerminate (filePath);
}
vStringCatS (filePath, file);
#endif
return filePath;
}
/* Return a newly-allocated string whose contents concatenate those of
* s1, s2, s3.
* Routine adapted from Gnu etags.
*/
static char* concat (const char *s1, const char *s2, const char *s3)
{
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
char *result = xMalloc (len1 + len2 + len3 + 1, char);
strcpy (result, s1);
strcpy (result + len1, s2);
strcpy (result + len1 + len2, s3);
result [len1 + len2 + len3] = '\0';
return result;
}
/* Return a newly allocated string containing the absolute file name of FILE
* given CWD (which should end with a slash).
* Routine adapted from Gnu etags.
*/
extern char* absoluteFilename (const char *file)
{
char *slashp, *cp;
char *res = NULL;
if (isAbsolutePath (file))
{
#ifdef MSDOS_STYLE_PATH
if (file [1] == ':')
res = eStrdup (file);
else
{
char drive [3];
sprintf (drive, "%c:", currentdrive ());
res = concat (drive, file, "");
}
#else
res = eStrdup (file);
#endif
}
else
res = concat (CurrentDirectory, file, "");
/* Delete the "/dirname/.." and "/." substrings. */
slashp = strchr (res, PATH_SEPARATOR);
while (slashp != NULL && slashp [0] != '\0')
{
if (slashp[1] == '.')
{
if (slashp [2] == '.' &&
(slashp [3] == PATH_SEPARATOR || slashp [3] == '\0'))
{
cp = slashp;
do
cp--;
while (cp >= res && ! isAbsolutePath (cp));
if (cp < res)
cp = slashp;/* the absolute name begins with "/.." */
#ifdef MSDOS_STYLE_PATH
/* Under MSDOS and NT we get `d:/NAME' as absolute file name,
* so the luser could say `d:/../NAME'. We silently treat this
* as `d:/NAME'.
*/
else if (cp [0] != PATH_SEPARATOR)
cp = slashp;
#endif
strcpy (cp, slashp + 3);
slashp = cp;
continue;
}
else if (slashp [2] == PATH_SEPARATOR || slashp [2] == '\0')
{
strcpy (slashp, slashp + 2);
continue;
}
}
slashp = strchr (slashp + 1, PATH_SEPARATOR);
}
if (res [0] == '\0')
return eStrdup ("/");
else
{
#ifdef MSDOS_STYLE_PATH
/* Canonicalize drive letter case. */
if (res [1] == ':' && islower (res [0]))
res [0] = toupper (res [0]);
#endif
return res;
}
}
/* Return a newly allocated string containing the absolute file name of dir
* where `file' resides given `CurrentDirectory'.
* Routine adapted from Gnu etags.
*/
extern char* absoluteDirname (char *file)
{
char *slashp, *res;
char save;
slashp = strrchr (file, PATH_SEPARATOR);
if (slashp == NULL)
res = eStrdup (CurrentDirectory);
else
{
save = slashp [1];
slashp [1] = '\0';
res = absoluteFilename (file);
slashp [1] = save;
}
return res;
}
/* Return a newly allocated string containing the file name of FILE relative
* to the absolute directory DIR (which should end with a slash).
* Routine adapted from Gnu etags.
*/
extern char* relativeFilename (const char *file, const char *dir)
{
const char *fp, *dp;
char *absdir, *res;
int i;
/* Find the common root of file and dir (with a trailing slash). */
absdir = absoluteFilename (file);
fp = absdir;
dp = dir;
while (*fp++ == *dp++)
continue;
fp--;
dp--; /* back to the first differing char */
do
{ /* look at the equal chars until path sep */
if (fp == absdir)
return absdir; /* first char differs, give up */
fp--;
dp--;
} while (*fp != PATH_SEPARATOR);
/* Build a sequence of "../" strings for the resulting relative file name.
*/
i = 0;
while ((dp = strchr (dp + 1, PATH_SEPARATOR)) != NULL)
i += 1;
res = xMalloc (3 * i + strlen (fp + 1) + 1, char);
res [0] = '\0';
while (i-- > 0)
strcat (res, "../");
/* Add the file name relative to the common root of file and dir. */
strcat (res, fp + 1);
free (absdir);
return res;
}
extern FILE *tempFile (const char *const mode, char **const pName)
{
char *name;
FILE *fp;
int fd;
#if defined(HAVE_MKSTEMP)
const char *const pattern = "tags.XXXXXX";
const char *tmpdir = NULL;
fileStatus *file = eStat (ExecutableProgram);
if (! file->isSetuid)
tmpdir = getenv ("TMPDIR");
if (tmpdir == NULL)
tmpdir = TMPDIR;
name = xMalloc (strlen (tmpdir) + 1 + strlen (pattern) + 1, char);
sprintf (name, "%s%c%s", tmpdir, OUTPUT_PATH_SEPARATOR, pattern);
fd = mkstemp (name);
#elif defined(HAVE_TEMPNAM)
name = tempnam (TMPDIR, "tags");
if (name == NULL)
error (FATAL | PERROR, "cannot allocate temporary file name");
fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
#else
name = xMalloc (L_tmpnam, char);
if (tmpnam (name) != name)
error (FATAL | PERROR, "cannot assign temporary file name");
fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
#endif
if (fd == -1)
error (FATAL | PERROR, "cannot open temporary file");
fp = fdopen (fd, mode);
if (fp == NULL)
error (FATAL | PERROR, "cannot open temporary file");
DebugStatement (
debugPrintf (DEBUG_STATUS, "opened temporary file %s\n", name); )
Assert (*pName == NULL);
*pName = name;
return fp;
}
/* vi:set tabstop=8 shiftwidth=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -