This is fileUtils.m in view mode; [Download] [Up]
// -------------------------------------------------------------------------------------
// misc file utilities
// -------------------------------------------------------------------------------------
// Permission is granted to freely redistribute this source code, and to use fragments
// of this code in your own applications if you find them to be useful. This class,
// along with the source code, come with no warranty of any kind, and the user assumes
// all responsibility for its use.
// -------------------------------------------------------------------------------------
#import <appkit/appkit.h>
#import <stdio.h>
#import <string.h>
#import <ctype.h>
#import <libc.h>
#import <pwd.h>
#import <mntent.h>
#import <sys/types.h>
#import <sys/stat.h>
#import <sys/param.h>
#import <sys/dir.h>
#import "fileUtils.h"
/* return file extension */
const char *XFileExtension(const char *file)
{
char *temp = rindex(file, '.');
return temp? temp : "";
}
/* return file name/extension */
const char *XFileNameExtension(const char *file)
{
char *temp = rindex(file, '/');
return temp? temp + 1 : file;
}
/* return true if file exists */
int XFileExists(const char *file)
{
struct stat st;
return file && !stat((char*)file,&st)? 1 : 0;
}
/* return true if file exists */
int XFileIsDirectory(const char *file)
{
struct stat st;
return file && !stat((char*)file,&st) && (st.st_mode & S_IFDIR)? 1 : 0;
}
/* return true if file exists */
int XFileIsLink(const char *file)
{
struct stat st;
return file && !lstat((char*)file,&st) && ((st.st_mode & S_IFMT)==S_IFLNK)? 1 : 0;
}
/* return true if file exists */
char *XFileReadLink(const char *file, char *link)
{
int len;
if (!XFileIsLink(file)) return (char*)NULL;
if ((len = readlink(file, link, MAXPATHLEN)) >= 0) link[len] = 0;
else *link = 0;
return len > 0? link : (char*)NULL;
}
/* return a file size */
long XFileSize(const char *file)
{
struct stat st;
return file && !stat((char*)file,&st)? st.st_size : -1L;
}
/* return current dir */
char *XCurrentDir(char *dir)
{
return (!dir || !getwd(dir))? (char*)NULL : dir;
}
/* change dir */
int XChangeDir(char *path)
{
return (!path || (chdir(path) < 0))? -1 : 0;
}
/* copy a file */
int XCopyFile(const char *fromName, const char *toName, int backup)
{
int fi = -1, fo = -1, c, stm, mode;
char b[10240], bku[MAXPATHLEN + 1];
struct stat st;
/* get file mode of toFile */
mode = ((stm = stat(toName, &st)) >= 0)? (st.st_mode & 0777) : 0644;
/* file already exist? */
if (backup && (stm >= 0)) {
sprintf(bku, "%s~", toName);
if (rename(toName, bku)) {
NXLogError("copyFile: Unable to rename %s to %s", toName, bku);
return -1;
}
}
/* remove to-file */
unlink(toName);
/* open/copy/close */
if (((fi = open(fromName, O_RDONLY)) >= 0) &&
((fo = open(toName, O_WRONLY | O_CREAT, 0666)) >= 0)) {
for (c = 0; !c && ((c = read(fi, b, sizeof(b))) > 0);) c -= write(fo, b, c);
} else c = -1;
if (fi >= 0) close(fi);
if (fo >= 0) close(fo);
/* restore backup if error */
if (c && backup && rename(bku, toName)) {
NXLogError("copyFile: Unable to restore backup %s after error", bku);
return -2;
}
return c? -3: 0;
}
/* return server and path to specified file (eg "server:/xyz/file") */
char *XMountPath(char *path, char *mountPath)
{
FILE *mNum;
struct mntent *m;
struct stat stpath, stdir;
char savName[MAXPATHLEN + 1], savPath[MAXPATHLEN + 1];
int sc;
/* init mountPath */
if (mountPath != path) *mountPath = 0;
/* make sure file exists */
if (!path || !*path || (stat(path, &stpath) < 0)) return (char*)NULL;
/* open mount table */
if (!(mNum = setmntent(MOUNTED, "r"))) return (char*)NULL;
/* find remote mount */
*savName = *savPath = 0;
for (sc = 0; m = getmntent(mNum); ) {
int l;
/* validation testing */
if (!strcmp(m->mnt_type, MNTTYPE_IGNORE)) continue; // ignored
if (!strcmp(m->mnt_type, MNTTYPE_SWAP )) continue; // ignored
if (stat(m->mnt_dir, &stdir) < 0) continue; // can't stat
if (stpath.st_dev != stdir.st_dev) continue; // same device
if (!(l = strlen(m->mnt_dir))) continue; // empty dir string
if (strncmp(m->mnt_dir, path, l)) continue; // not equal
/* save dir */
if (!path[l] || (path[l] == '/')) {
char *c = m->mnt_dir;
int n = 0;
for (; *c; c++) { if (*c == '/') n++; }
if (!sc || (n > sc)) {
sc = n;
strcpy(savName, m->mnt_fsname);
strcpy(savPath, path + l);
}
} else
if ((l == 1) && (*m->mnt_dir == '/') && !sc) {
strcpy(savName, m->mnt_fsname);
strcpy(savPath, path);
}
}
/* build mounted path */
if (index(savName, ':')) {
sprintf(mountPath, "%s%s", savName, savPath);
} else {
char *sName = strncmp(savName,"/dev/",5)? savName : savName + 5;
char *sPath = *savPath? savPath: "/";
sprintf(mountPath, "#%s:%s", sName, sPath);
}
return mountPath;
}
/* resolve all symbolic links in file path */
char *XResolveLinks(char *path, char *nPath) // can do in-place conversion
{
char wPath[MAXPATHLEN+1], *p, *t;
/* init nPath */
if (nPath != path) *nPath = 0;
/* return if path not specified */
if (!path || !*path) return (char*)NULL;
/* create absolute path to file */
if (*path == '/') strcpy(wPath, path); else
if (*path == '~') {
struct passwd *pw;
char user[128], *p = path + 1;
{ char *u = user; for (;*p && (*p != '/');) *u++ = *p++; *u = 0; }
if (!(pw = *user? getpwnam(user) : getpwuid(getuid()))) return (char*)NULL;
sprintf(wPath, "%s%s", pw->pw_dir, p);
} else {
char curdir[MAXPATHLEN + 1];
if (!getwd(curdir)) return (char*)NULL;
sprintf(wPath, "%s/%s", curdir, path);
}
/* resolve all symbolic links in path */
for (p = wPath, t = nPath; ; *t++ = *p++) {
if ((!*p || (*p == '/')) && (t > nPath)) {
int l;
struct stat st;
char sl[MAXPATHLEN + 1], *cp;
*t = 0;
cp = rindex(nPath, '/'); // should never be null
if ((lstat(nPath,&st) >= 0) && ((st.st_mode & S_IFMT) == S_IFLNK) &&
((l = readlink(nPath, sl, sizeof(sl)-1)) > 0)) {
sl[l] = 0;
if (*sl == '/') { // recursion to resolve new link
XResolveLinks(sl, nPath);
} else {
*++cp = 0;
strcpy(cp, sl);
XResolveLinks(nPath, nPath);
}
t = nPath + strlen(nPath);
} else
if (!*(cp + 1)) { // ignore duplicate '/'
*(t = cp) = 0;
} else
if (!strcmp(cp, "/.")) { // ignore self references
*(t = cp) = 0;
} else
if (!strcmp(cp, "/..")) { // back up path
*(t = cp) = 0;
if (cp = rindex(nPath, '/')) *(t = cp) = 0;
}
}
if (!*p) break;
}
*t = 0;
if (!*nPath) strcpy(nPath, "/");
return nPath;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.