home *** CD-ROM | disk | FTP | other *** search
- // -------------------------------------------------------------------------------------
- // 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;
- }
-