#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "fileUtils.h"
#include "utils.h"
#include "nedit_malloc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <X11/Intrinsic.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
#ifndef MAXSYMLINKS
#define MAXSYMLINKS 20
#endif
#define TRUE 1
#define FALSE 0
#define FORMAT_SAMPLE_LINES 5
#define FORMAT_SAMPLE_CHARS 2000
static char *nextSlash(
char *ptr);
static char *prevSlash(
char *ptr);
static int compareThruSlash(
const char *string1,
const char *string2);
static void copyThruSlash(
char **toString,
char **fromString);
int
ParseFilename(
const char *fullname,
char *filename,
char *pathname)
{
int fullLen = strlen(fullname);
int i, pathLen, fileLen;
char *viewExtendPath;
int scanStart;
if ((viewExtendPath = strstr(fullname,
"@@/")) !=
NULL)
scanStart = viewExtendPath - fullname -
1;
else
scanStart = fullLen -
1;
for (i=scanStart; i>=
0; i--) {
if (fullname[i] ==
'/')
break;
}
pathLen = i +
1;
fileLen = fullLen - pathLen;
if (pathname) {
if (pathLen >=
MAXPATHLEN) {
return 1;
}
strncpy(pathname, fullname, pathLen);
pathname[pathLen] =
0;
}
if (filename) {
if (fileLen >=
MAXPATHLEN) {
return 2;
}
strncpy(filename, &fullname[pathLen], fileLen);
filename[fileLen] =
0;
}
#ifndef VMS
if(pathname) {
if (NormalizePathname(pathname)) {
return 1;
}
pathLen = strlen(pathname);
}
#endif
if (filename && pathname && ((pathLen +
1 + fileLen) >=
MAXPATHLEN)) {
return 1;
}
return 0;
}
#ifndef VMS
int
ExpandTilde(
char *pathname)
{
struct passwd *passwdEntry;
char username[
MAXPATHLEN], temp[
MAXPATHLEN];
char *nameEnd;
unsigned len_left;
if (pathname[
0] !=
'~')
return TRUE;
nameEnd = strchr(&pathname[
1],
'/');
if (nameEnd ==
NULL) {
nameEnd = pathname + strlen(pathname);
}
strncpy(username, &pathname[
1], nameEnd - &pathname[
1]);
username[nameEnd - &pathname[
1]] =
'\0';
if (username[
0] ==
'\0') {
passwdEntry = getpwuid(getuid());
if ((passwdEntry ==
NULL) || (*(passwdEntry->pw_dir)==
'\0')) {
perror(
"XNEdit/nc: getpwuid() failed ");
exit(
EXIT_FAILURE);
}
}
else {
passwdEntry = getpwnam(username);
if ((passwdEntry ==
NULL) || (*(passwdEntry->pw_dir)==
'\0')) {
return FALSE;
}
}
strcpy(temp, passwdEntry->pw_dir);
strcat(temp,
"/");
len_left=
sizeof(temp)-strlen(temp)-
1;
if (len_left < strlen(nameEnd)) {
return FALSE;
}
strcat(temp, nameEnd);
strcpy(pathname, temp);
return TRUE;
}
int
ResolvePath(
const char * pathIn,
char * pathResolved)
{
char resolveBuf[
MAXPATHLEN], pathBuf[
MAXPATHLEN];
char *pathEnd;
int rlResult, loops;
#ifdef NO_READLINK
strncpy(pathResolved, pathIn,
MAXPATHLEN);
return TRUE;
#else
for (loops=
0; loops<
MAXSYMLINKS; loops++) {
#ifdef UNICOS
rlResult=readlink((
char *)pathIn, resolveBuf,
MAXPATHLEN-
1);
#else
rlResult=readlink(pathIn, resolveBuf,
MAXPATHLEN-
1);
#endif
if (rlResult<
0) {
#ifndef __Lynx__
if (errno ==
EINVAL)
#else
if (errno ==
ENXIO)
#endif
{
strncpy(pathResolved, pathIn,
MAXPATHLEN);
pathResolved[
MAXPATHLEN-
1] =
'\0';
return TRUE;
}
else {
return FALSE;
}
}
else if (rlResult ==
0) {
return FALSE;
}
resolveBuf[rlResult]=
0;
if (resolveBuf[
0]!=
'/') {
strncpy(pathBuf, pathIn,
MAXPATHLEN);
pathBuf[
MAXPATHLEN-
1] =
'\0';
pathEnd=strrchr(pathBuf,
'/');
if (!pathEnd) {
return FALSE;
}
strcpy(pathEnd+
1, resolveBuf);
}
else {
strcpy(pathBuf, resolveBuf);
}
NormalizePathname(pathBuf);
pathIn=pathBuf;
}
return FALSE;
#endif
}
int NormalizePathname(
char *pathname)
{
#ifdef __EMX__
if (!_fnisabs(pathname)) {
#else
if (pathname[
0] !=
'/') {
#endif
char *oldPathname;
size_t len;
oldPathname=(
char *)malloc(strlen(pathname)+
1);
strcpy(oldPathname, pathname);
strcpy(pathname, GetCurrentDir());
len = strlen(pathname);
if (
0 == len ?
1 : pathname[len-
1] !=
'/')
{
strcat(pathname,
"/");
}
strcat(pathname, oldPathname);
free(oldPathname);
}
return CompressPathname(pathname);
}
int CompressPathname(
char *pathname)
{
char *buf, *inPtr, *outPtr;
struct stat statbuf;
inPtr = pathname;
buf = (
char*) malloc(strlen(pathname) +
2);
outPtr = buf;
*outPtr++ = *inPtr++;
while (*inPtr)
{
*outPtr = *inPtr++;
if (
'/' == *outPtr)
{
while (
'/' == *inPtr)
{
inPtr++;
}
}
outPtr++;
}
*outPtr=
0;
strcpy(pathname, buf);
inPtr = pathname;
outPtr = buf;
copyThruSlash(&outPtr, &inPtr);
while (inPtr !=
NULL) {
if (compareThruSlash(inPtr,
"../")) {
*outPtr =
0;
#ifdef S_ISLNK
if(outPtr-
1 == buf || (lstat(buf, &statbuf) ==
0 &&
S_ISLNK(statbuf.st_mode))) {
copyThruSlash(&outPtr, &inPtr);
}
else
#endif
{
outPtr = prevSlash(outPtr);
inPtr = nextSlash(inPtr);
}
}
else if (compareThruSlash(inPtr,
"./")) {
inPtr = nextSlash(inPtr);
}
else {
copyThruSlash(&outPtr, &inPtr);
}
}
if (strlen(buf)>
MAXPATHLEN) {
fprintf(stderr,
"nedit: CompressPathname(): file name too long %s\n",
pathname);
free(buf);
return 1;
}
else {
strcpy(pathname, buf);
free(buf);
return 0;
}
}
static char
*nextSlash(
char *ptr)
{
for(; *ptr!=
'/'; ptr++) {
if (*ptr ==
'\0')
return NULL;
}
return ptr +
1;
}
static char
*prevSlash(
char *ptr)
{
for(ptr -=
2; *ptr!=
'/'; ptr--);
return ptr +
1;
}
static int
compareThruSlash(
const char *string1,
const char *string2)
{
while (
TRUE) {
if (*string1 != *string2)
return FALSE;
if (*string1 ==
'\0' || *string1==
'/')
return TRUE;
string1++;
string2++;
}
}
static void
copyThruSlash(
char **toString,
char **fromString)
{
char *to = *toString;
char *from = *fromString;
while (
TRUE) {
*to = *from;
if (*from ==
'\0') {
*fromString =
NULL;
return;
}
if (*from==
'/') {
*toString = to +
1;
*fromString = from +
1;
return;
}
from++;
to++;
}
}
#else
int NormalizePathname(
char *pathname)
{
return 0;
}
int CompressPathname(
char *pathname)
{
return 0;
}
int ResolvePath(
const char * pathIn,
char * pathResolved)
{
if (strlen(pathIn) <
MAXPATHLEN) {
strcpy(pathResolved, pathIn);
return TRUE;
}
else {
return FALSE;
}
}
#endif
const char
*GetTrailingPathComponents(
const char* path,
int noOfComponents)
{
const char* ptr = path + strlen(path);
int count =
0;
while (--ptr > path) {
if (*ptr ==
'/') {
if (count++ == noOfComponents) {
break;
}
}
}
return(ptr);
}
int FormatOfFile(
const char *fileString)
{
const char *p;
int nNewlines =
0, nReturns =
0;
for (p=fileString; *p!=
'\0' && p < fileString +
FORMAT_SAMPLE_CHARS; p++) {
if (*p ==
'\n') {
nNewlines++;
if (p == fileString || *(p-
1) !=
'\r')
return UNIX_FILE_FORMAT;
if (nNewlines >=
FORMAT_SAMPLE_LINES)
return DOS_FILE_FORMAT;
}
else if (*p ==
'\r')
nReturns++;
}
if (nNewlines >
0)
return DOS_FILE_FORMAT;
if (nReturns >
0)
return MAC_FILE_FORMAT;
return UNIX_FILE_FORMAT;
}
void ConvertFromDosFileString(
char *fileString,
int *length,
char* pendingCR)
{
char *outPtr = fileString;
char *inPtr = fileString;
if (pendingCR) *pendingCR =
0;
while (inPtr < fileString + *length) {
if (*inPtr ==
'\r') {
if (inPtr < fileString + *length -
1) {
if (*(inPtr +
1) ==
'\n')
inPtr++;
}
else {
if (pendingCR) {
*pendingCR = *inPtr;
break;
}
}
}
*outPtr++ = *inPtr++;
}
*outPtr =
'\0';
*length = outPtr - fileString;
}
void ConvertFromMacFileString(
char *fileString,
int length)
{
char *inPtr = fileString;
while (inPtr < fileString + length) {
if (*inPtr ==
'\r' )
*inPtr =
'\n';
inPtr++;
}
}
int ConvertToDosFileString(
char **fileString,
int *length)
{
char *outPtr, *outString;
char *inPtr = *fileString;
int inLength = *length;
int outLength =
0;
while (inPtr < *fileString + inLength) {
if (*inPtr ==
'\n')
outLength++;
inPtr++;
outLength++;
}
outString = (
char*)malloc(outLength +
1);
if (outString ==
NULL)
return FALSE;
inPtr = *fileString;
outPtr = outString;
while (inPtr < *fileString + inLength) {
if (*inPtr ==
'\n')
*outPtr++ =
'\r';
*outPtr++ = *inPtr++;
}
*outPtr =
'\0';
NEditFree(*fileString);
*fileString = outString;
*length = outLength;
return TRUE;
}
void ConvertToMacFileString(
char *fileString,
int length)
{
char *inPtr = fileString;
while (inPtr < fileString + length) {
if (*inPtr ==
'\n' )
*inPtr =
'\r';
inPtr++;
}
}
char *ReadAnyTextFile(
const char *fileName,
int forceNL)
{
struct stat statbuf;
FILE *fp;
int fileLen, readLen;
char *fileString;
int format;
if ((fp = fopen(fileName,
"r")) ==
NULL) {
return NULL;
}
if (fstat(fileno(fp), &statbuf) !=
0) {
fclose(fp);
return NULL;
}
fileLen = statbuf.st_size;
fileString = (
char*)NEditMalloc(fileLen +
2);
readLen = fread(fileString,
sizeof(
char), fileLen, fp);
if (ferror(fp)) {
NEditFree(fileString);
fclose(fp);
return NULL;
}
fclose(fp);
fileString[readLen] =
0;
format = FormatOfFile(fileString);
if (format ==
DOS_FILE_FORMAT){
char pendingCR;
ConvertFromDosFileString(fileString, &readLen, &pendingCR);
}
else if (format ==
MAC_FILE_FORMAT){
ConvertFromMacFileString(fileString, readLen);
}
if (forceNL && fileString[readLen -
1] !=
'\n') {
fileString[readLen] =
'\n';
fileString[readLen +
1] =
'\0';
}
return fileString;
}