#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include "Clean.h"
#ifndef NAME_MAX
#define NAME_MAX 500
#endif
#define FALSE 0
#define TRUE (!FALSE)
// error codes:
#define NoDirError 0
#define OtherDirError -1
#define DoesntExist -2
#define BadName -3
#define NotEnoughSpace -4
#define AlreadyExists -5
#define NoPermission -6
#define MoveIntoOffspring -7
#define MoveAcrossDisks -8
#define NotYetRemovable -9
uid_t gUserId;
gid_t gGroupId;
struct DIR *gpDir;
struct dirent *gpDirent;
struct stat gFileStat;
char *gPath;
int gPathLength;
CleanStringVariable(gFileName,NAME_MAX+1);
static int unix_error_to_clean_error(int errCode)
{
switch(errCode) {
case ENOENT:
case ENOTDIR: return DoesntExist;
case ENAMETOOLONG: return BadName;
case EMLINK:
case ENOSPC: return NotEnoughSpace;
case EISDIR:
case EEXIST: return AlreadyExists;
case EPERM:
case EACCES:
case EROFS: return NoPermission;
case EINVAL: return MoveIntoOffspring;
case EXDEV: return MoveAcrossDisks;
case ENOTEMPTY: return NotYetRemovable;
default: return OtherDirError;
};
}
static int openSearch(const char *path, int length)
{
int i;
gPathLength = length;
gPath = (char*) malloc(gPathLength+NAME_MAX+2);
if (!gPath) {
gpDir = NULL;
return 0;
}
else {
memcpy(gPath, path, gPathLength);
gPath[gPathLength] = '\0';
gpDir = (struct DIR*) opendir(gPath);
if (!gpDir)
return unix_error_to_clean_error(errno);
gPath[gPathLength] = '/'; // filename will be added later
gUserId = getuid();
gGroupId = getgid();
return NoDirError;
};
}
int findFirstFileC(CleanString cs_path)
{
int errCode;
errCode = openSearch(CleanStringCharacters(cs_path), CleanStringLength(cs_path));
if (errCode)
return errCode;
else
return findNextFileC(0);
}
void getCommonFileInfoC(int also_get_file_name,
CleanString *pFileName, int *pFileSizeLow, int *pFileSizeHigh,
int *pYear, int *pMonth, int *pDay, int *pDayNr,
int *pHours, int *pMinutes, int *pSeconds,
int *pIsDirectory, int *pIsReadOnly)
// requires gFileName and gFileStat to be initialized
{
struct tm *pModificationTime;
int mask;
static int null = 0;
*pFileName = also_get_file_name ? (CleanString) gFileName : (CleanString) &null;
*pFileSizeLow = gFileStat.st_size;
*pFileSizeHigh = 0;
pModificationTime= localtime(&gFileStat.st_mtime);
*pYear = pModificationTime->tm_year+1900;
*pMonth = pModificationTime->tm_mon+1;
*pDay = pModificationTime->tm_mday;
*pDayNr = pModificationTime->tm_wday+1;
*pHours = pModificationTime->tm_hour;
*pMinutes = pModificationTime->tm_min;
*pSeconds = pModificationTime->tm_sec % 60;
*pIsDirectory = (gFileStat.st_mode & S_IFDIR) != 0;
mask = gUserId==gFileStat.st_uid ? S_IWUSR
: gGroupId==gFileStat.st_gid ? S_IWGRP
: S_IWOTH;
*pIsReadOnly = (gFileStat.st_mode & mask) == 0;
}
int findNextFileC(int dummy)
// return values: 0=ok, 1=no further files in directory
{
int i;
gpDirent = readdir((void*)gpDir);
if (!gpDirent)
return 1;
for(i=0; gpDirent->d_name[i]!='\0' && i<NAME_MAX; i++) {
CleanStringCharacters(gFileName)[i] = gpDirent->d_name[i];
gPath[gPathLength+1+i] = gpDirent->d_name[i];
};
CleanStringLength(gFileName)= i;
gPath[gPathLength+1+i] = '\0';
gFileStat.st_size = 0;
gFileStat.st_mode = 0;
lstat(gPath,&gFileStat);
return 0;
}
int getPlatformIdC(int dummy)
{
#define UnixPlatform 0
return UnixPlatform;
}
void getWindowsFileInfoC()
{}
void getMacFileInfoC()
{}
void getUnixFileInfoC(int *pModeBits, int *pOwnerUserId, int *pOwnerGroupId,
int *pLAYear, int *pLAMonth, int *pLADay, int *pLADayNr, // last access time
int *pLAHours, int *pLAMinutes, int *pLASeconds) // dito
{
struct tm *pModificationTime;
*pModeBits = gFileStat.st_mode;
*pOwnerUserId = gFileStat.st_uid;
*pOwnerGroupId = gFileStat.st_gid;
pModificationTime= localtime(&gFileStat.st_atime);
*pLAYear = pModificationTime->tm_year+1900;
*pLAMonth = pModificationTime->tm_mon+1;
*pLADay = pModificationTime->tm_mday;
*pLADayNr = pModificationTime->tm_wday+1;
*pLAHours = pModificationTime->tm_hour;
*pLAMinutes = pModificationTime->tm_min;
*pLASeconds = pModificationTime->tm_sec % 60;
}
void closeSearchC()
{
free(gPath);
if (gpDir)
closedir((void*)gpDir);
}
int findSingleFileC(CleanString cs_path)
{
int err,i,length;
char *path_chars;
gFileStat.st_size = 0;
gFileStat.st_mode = 0;
path_chars = CleanStringCharacters(cs_path);
if (lstat(path_chars,&gFileStat))
return unix_error_to_clean_error(errno);
i = CleanStringLength(cs_path)-2;
while (i>=0 && path_chars[i]!='/')
i--;
// the last path element ranges from path_chars[i+1] to path_chars[CleanStringLength(cs_path)-2]
length = CleanStringLength(cs_path)-2-i;
CleanStringLength(gFileName) = length;
memcpy(CleanStringCharacters(gFileName), path_chars+i+1, length);
return NoDirError;
}
void closeSingleSearchC()
{}
int createDirectoryC(CleanString cs_path)
{
int err;
err = mkdir(CleanStringCharacters(cs_path),
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
// access rights for newly created directory: rwx--x--x
if (err)
return unix_error_to_clean_error(errno);
else
return NoDirError;
}
int fremoveC(CleanString cs_path)
{
int err;
err = remove(CleanStringCharacters(cs_path));
if (err) {
if (errno==EEXIST)
return NotYetRemovable;
else
return unix_error_to_clean_error(errno);
}
else
return NoDirError;
}
// Try this code with slackware linux, if the testLinux program doesn't work
//int fremoveC(CleanString cs_path)
//{
// int err;
//
// err = unlink(CleanStringCharacters(cs_path));
// if (err) {
// if (errno==EPERM) {
// err = rmdir(CleanStringCharacters(cs_path));
// if (err)
// return unix_error_to_clean_error(errno);
// else
// return NoDirError;
// }
// else
// return unix_error_to_clean_error(errno);
// }
// else
// return NoDirError;
//}
#define OK 0
#define STRING_TOO_SMALL 1
int getCurrentDirectory_SE(CleanString cs)
{
if (getcwd(CleanStringCharacters(cs), CleanStringLength(cs))) {
// success. convert C String to Clean string
int i;
i = 0;
while(CleanStringCharacters(cs)[i]!='\0')
i++;
CleanStringLength(cs) = i;
return OK;
}
else {
// failure
if (errno==EACCES) {
// the permission to read the current directory was denied (how ever)
// return root directory
CleanStringLength(cs) = 1;
CleanStringCharacters(cs)[0] = '/';
return OK;
}
else
return STRING_TOO_SMALL;
};
}
void get_mac_dir_parent_and_name_C()
{
}
int setCurrentDirectoryC(CleanString csPath)
{
int err;
err = chdir(CleanStringCharacters(csPath));
if (err)
return unix_error_to_clean_error(errno);
else
return NoDirError;
}
void getMacDiskNameC()
{}
void get_windows_disk_available_bits_C()
{}
void macRenameC()
{}
void macMoveC()
{}
int fmoveC(int overwrite, CleanString from, CleanString to)
{
int err,clean_err;
if (overwrite) {
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
if (err && errno==ENOTDIR) {
// from is a directory and to a file
// try again after removing to
err = remove(CleanStringCharacters(to));
if (!err)
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
};
clean_err = err ? unix_error_to_clean_error(errno) : NoDirError;
}
else {
struct stat fileStat;
if (stat(CleanStringCharacters(to),&fileStat)) {
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
clean_err = err ? unix_error_to_clean_error(errno) : NoDirError;
}
else
clean_err = AlreadyExists;
};
return clean_err;
}