home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / NeXT-Icons / next-icon@gun.com / Apps / ImagePortfolio / apputils.subproj / fileUtils.m < prev    next >
Encoding:
Text File  |  1993-06-03  |  6.5 KB  |  251 lines

  1. // -------------------------------------------------------------------------------------
  2. // misc file utilities
  3. // -------------------------------------------------------------------------------------
  4. // Permission is granted to freely redistribute this source code, and to use fragments
  5. // of this code in your own applications if you find them to be useful.  This class,
  6. // along with the source code, come with no warranty of any kind, and the user assumes
  7. // all responsibility for its use.
  8. // -------------------------------------------------------------------------------------
  9.  
  10. #import <appkit/appkit.h>
  11. #import <stdio.h>
  12. #import <string.h>
  13. #import <ctype.h>
  14. #import <libc.h>
  15. #import <pwd.h>
  16. #import <mntent.h>
  17. #import <sys/types.h>
  18. #import <sys/stat.h>
  19. #import <sys/param.h>
  20. #import <sys/dir.h>
  21. #import "fileUtils.h"
  22.  
  23. /* return file extension */
  24. const char *XFileExtension(const char *file)
  25. {
  26.     char    *temp = rindex(file, '.');
  27.     return temp? temp : "";
  28. }
  29.  
  30. /* return file name/extension */
  31. const char *XFileNameExtension(const char *file)
  32. {
  33.     char    *temp = rindex(file, '/');
  34.     return temp? temp + 1 : file;
  35. }
  36.  
  37. /* return true if file exists */
  38. int XFileExists(const char *file)
  39. {
  40.     struct stat    st;
  41.     return file && !stat((char*)file,&st)? 1 : 0;
  42. }
  43.  
  44. /* return true if file exists */
  45. int XFileIsDirectory(const char *file)
  46. {
  47.     struct stat    st;
  48.     return file && !stat((char*)file,&st) && (st.st_mode & S_IFDIR)? 1 : 0;
  49. }
  50.  
  51. /* return true if file exists */
  52. int XFileIsLink(const char *file)
  53. {
  54.     struct stat    st;
  55.     return file && !lstat((char*)file,&st) && ((st.st_mode & S_IFMT)==S_IFLNK)? 1 : 0;
  56. }
  57.  
  58. /* return true if file exists */
  59. char *XFileReadLink(const char *file, char *link)
  60. {
  61.     int    len;
  62.     if (!XFileIsLink(file)) return (char*)NULL;
  63.     if ((len = readlink(file, link, MAXPATHLEN)) >= 0) link[len] = 0;
  64.     else *link = 0;
  65.     return len > 0? link : (char*)NULL;
  66. }
  67.  
  68. /* return a file size */
  69. long XFileSize(const char *file)
  70. {
  71.     struct stat    st;
  72.     return file && !stat((char*)file,&st)? st.st_size : -1L;
  73. }
  74.  
  75. /* return current dir */
  76. char *XCurrentDir(char *dir)
  77. {
  78.     return (!dir || !getwd(dir))? (char*)NULL : dir;
  79. }
  80.  
  81. /* change dir */
  82. int XChangeDir(char *path)
  83. {
  84.     return (!path || (chdir(path) < 0))? -1 : 0;
  85. }
  86.  
  87. /* copy a file */
  88. int XCopyFile(const char *fromName, const char *toName, int backup)
  89. {
  90.     int            fi = -1, fo = -1, c, stm, mode;
  91.     char        b[10240], bku[MAXPATHLEN + 1];
  92.     struct stat    st;
  93.  
  94.     /* get file mode of toFile */
  95.     mode = ((stm = stat(toName, &st)) >= 0)? (st.st_mode & 0777) : 0644;
  96.     
  97.     /* file already exist? */
  98.     if (backup && (stm >= 0)) {
  99.         sprintf(bku, "%s~", toName);
  100.         if (rename(toName, bku)) {
  101.             NXLogError("copyFile: Unable to rename %s to %s", toName, bku);
  102.             return -1;
  103.         }
  104.     }
  105.  
  106.     /* remove to-file */
  107.     unlink(toName);
  108.  
  109.     /* open/copy/close */
  110.     if (((fi = open(fromName, O_RDONLY)) >= 0) &&
  111.         ((fo = open(toName, O_WRONLY | O_CREAT, 0666)) >= 0)) {
  112.         for (c = 0; !c && ((c = read(fi, b, sizeof(b))) > 0);) c -= write(fo, b, c);
  113.     } else c = -1;
  114.     if (fi >= 0) close(fi);
  115.     if (fo >= 0) close(fo);
  116.     
  117.     /* restore backup if error */
  118.     if (c && backup && rename(bku, toName)) {
  119.         NXLogError("copyFile: Unable to restore backup %s after error", bku);
  120.         return -2;
  121.     }
  122.     
  123.     return c? -3: 0;
  124.     
  125. }
  126.  
  127. /* return server and path to specified file (eg "server:/xyz/file") */
  128. char *XMountPath(char *path, char *mountPath)
  129. {
  130.     FILE            *mNum;
  131.     struct mntent    *m;
  132.     struct stat        stpath, stdir;
  133.     char            savName[MAXPATHLEN + 1], savPath[MAXPATHLEN + 1];
  134.     int                sc;
  135.  
  136.     /* init mountPath */
  137.     if (mountPath != path) *mountPath = 0;
  138.  
  139.     /* make sure file exists */
  140.     if (!path || !*path || (stat(path, &stpath) < 0)) return (char*)NULL;
  141.     
  142.     /* open mount table */
  143.     if (!(mNum = setmntent(MOUNTED, "r"))) return (char*)NULL;
  144.  
  145.     /* find remote mount */
  146.     *savName = *savPath = 0;
  147.     for (sc = 0; m = getmntent(mNum); ) {
  148.         int l;
  149.         
  150.         /* validation testing */
  151.         if (!strcmp(m->mnt_type, MNTTYPE_IGNORE)) continue;        // ignored
  152.         if (!strcmp(m->mnt_type, MNTTYPE_SWAP  )) continue;        // ignored
  153.         if (stat(m->mnt_dir, &stdir) < 0) continue;                // can't stat
  154.         if (stpath.st_dev != stdir.st_dev) continue;            // same device
  155.         if (!(l = strlen(m->mnt_dir))) continue;                // empty dir string
  156.         if (strncmp(m->mnt_dir, path, l)) continue;                // not equal
  157.         
  158.         /* save dir */
  159.         if (!path[l] || (path[l] == '/')) {
  160.             char *c = m->mnt_dir;
  161.             int n = 0;
  162.             for (; *c; c++) { if (*c == '/') n++; }
  163.             if (!sc || (n > sc)) {
  164.                 sc = n;
  165.                 strcpy(savName, m->mnt_fsname);
  166.                 strcpy(savPath, path + l);
  167.             }
  168.         } else
  169.         if ((l == 1) && (*m->mnt_dir == '/') && !sc) {
  170.             strcpy(savName, m->mnt_fsname);
  171.             strcpy(savPath, path);
  172.         }
  173.         
  174.     }
  175.     
  176.     /* build mounted path */
  177.     if (index(savName, ':')) {
  178.         sprintf(mountPath, "%s%s", savName, savPath);
  179.     } else {
  180.         char *sName = strncmp(savName,"/dev/",5)? savName : savName + 5;
  181.         char *sPath = *savPath? savPath: "/";
  182.         sprintf(mountPath, "#%s:%s", sName, sPath);
  183.     }
  184.     
  185.     return mountPath;
  186. }
  187.  
  188. /* resolve all symbolic links in file path */
  189. char *XResolveLinks(char *path, char *nPath)    // can do in-place conversion
  190. {
  191.     char wPath[MAXPATHLEN+1], *p, *t;
  192.  
  193.     /* init nPath */
  194.     if (nPath != path) *nPath = 0;
  195.  
  196.     /* return if path not specified */
  197.     if (!path || !*path) return (char*)NULL;
  198.     
  199.     /* create absolute path to file */
  200.     if (*path == '/') strcpy(wPath, path); else
  201.     if (*path == '~') {
  202.         struct passwd *pw;
  203.         char user[128], *p = path + 1;
  204.         { char *u = user; for (;*p && (*p != '/');) *u++ = *p++; *u = 0; }
  205.         if (!(pw = *user? getpwnam(user) : getpwuid(getuid()))) return (char*)NULL;
  206.         sprintf(wPath, "%s%s", pw->pw_dir, p);
  207.     } else {
  208.         char curdir[MAXPATHLEN + 1];
  209.         if (!getwd(curdir)) return (char*)NULL;
  210.         sprintf(wPath, "%s/%s", curdir, path);
  211.     }
  212.  
  213.     /* resolve all symbolic links in path */
  214.     for (p = wPath, t = nPath; ; *t++ = *p++) {
  215.         if ((!*p || (*p == '/')) && (t > nPath)) {
  216.             int l;
  217.             struct stat st;
  218.             char sl[MAXPATHLEN + 1], *cp;
  219.             *t = 0;
  220.             cp = rindex(nPath, '/');    // should never be null
  221.             if ((lstat(nPath,&st) >= 0) && ((st.st_mode & S_IFMT) == S_IFLNK) &&
  222.                     ((l = readlink(nPath, sl, sizeof(sl)-1)) > 0)) {
  223.                 sl[l] = 0;
  224.                 if (*sl == '/') {        // recursion to resolve new link
  225.                     XResolveLinks(sl, nPath);
  226.                 } else {
  227.                     *++cp = 0;
  228.                     strcpy(cp, sl);
  229.                     XResolveLinks(nPath, nPath);
  230.                 }
  231.                 t = nPath + strlen(nPath);
  232.             } else
  233.             if (!*(cp + 1)) {            // ignore duplicate '/'
  234.                 *(t = cp) = 0;
  235.             } else
  236.             if (!strcmp(cp, "/.")) {    // ignore self references
  237.                 *(t = cp) = 0;
  238.             } else
  239.             if (!strcmp(cp, "/..")) {    // back up path
  240.                 *(t = cp) = 0;
  241.                 if (cp = rindex(nPath, '/')) *(t = cp) = 0;
  242.             }
  243.         }
  244.         if (!*p) break;
  245.     }
  246.     *t = 0;
  247.     if (!*nPath) strcpy(nPath, "/");
  248.  
  249.     return nPath;
  250. }
  251.