Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / DetermineFileLocality.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *      $TOG: DetermineFileLocality.C /main/9 1997/12/22 16:30:59 bill $
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *       
30  *      The information in this document is subject to special
31  *      restrictions in a confidential disclosure agreement between
32  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
34  *      Sun's specific written approval.  This document and all copies
35  *      and derivative works thereof must be returned or destroyed at
36  *      Sun's request.
37  *
38  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  *
40  *+ENOTICE
41  */
42
43 #include <sys/types.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <assert.h>
49
50 #if defined(SVR4)
51 #include <sys/stat.h>
52 #include <sys/statvfs.h>
53 #include <sys/mnttab.h>
54 #include <sys/mntent.h>
55 #include <sys/param.h>
56 #endif
57
58 #include <DtMail/DtMail.hh>
59
60 /*
61  * Returns: length of second argument if it is a prefix of the
62  * first argument, otherwise zero.
63  */
64 static int
65 preflen(char * str, char * pref)
66 {
67   int len;
68
69   assert(str != NULL);
70   assert(pref != NULL);
71
72   len = strlen(pref);
73   if (strncmp(str, pref, len) == 0)
74     return (len);
75   return (0);
76 }
77
78 // DetermineFileLocality -- determine if specified path object is local
79 //              or remote to the current system
80 // Arguments:
81 //  const char * path   -- -> path to object whose locality is to be determined
82 // Outputs:
83 //  None.
84 // Returns:
85 //  (DtmFileLocality) -- determined locality of the specified path object:
86 //      FL_UNKNOWN      -- locality of object cannot be determined
87 //      FL_LOCAL        -- the path object is local to this system
88 //      FL_REMOTE       -- the path object is remote to this system
89 //                      -- (such as an NFS mounted file system object)
90 //      FL_LOCAL_AND_REMOTE -- the path object is locally available, yet
91 //                      -- it resides remotely (such as a CACHEFS object)
92 //
93
94 enum DtmFileLocality
95 DtMail::DetermineFileLocality(const char * path)
96 {
97 #if defined(SVR4)
98   FILE *mfp;
99   struct mnttab *mnt;
100   struct mnttab sysvmnt;
101   int fsTypeLen = 0;
102   int len;
103   char realPath[MAXPATHLEN];            // resolved symbolic link
104   char linkname[MAXPATHLEN];            // for symbolic link chasing
105   char fsType[MAXPATHLEN];              // fs type for name put here
106   struct statvfs statbuf;
107   int statvfs_successful = 0;
108
109
110   // Make sure the inputs to this function are correct
111   //
112   assert(path);                 // path must be specified
113   assert(strlen(path));         // cannot have a zero length
114
115
116   // Resolve all symbolic links in path so that we have a handle
117   // on the name of the actual file to check up on
118   //
119   (void) strncpy(realPath, path, MAXPATHLEN-1);
120   while (1) {
121     if ((len = readlink(realPath, linkname, sizeof (linkname)-1)) < 0)
122         break;
123     linkname[len] = '\0';
124     (void) strncpy(realPath, linkname, MAXPATHLEN-1);
125   }
126
127   // Try and determine where this file is located relative to here
128   //
129
130   for (int i = 0; ; i++)
131   {
132     fsTypeLen = 0;
133
134     switch (i)
135     {
136     case 0:                     // first instance -- try statvfs            
137       statbuf.f_files = 0;
138       if (statvfs (realPath, &statbuf) == -1)
139           continue;
140       statvfs_successful++;
141       fsTypeLen = strlen(statbuf.f_basetype);
142       (void) strncpy(fsType, statbuf.f_basetype, MAXPATHLEN-1);
143       break;
144
145     case 1:                     // second instance -- scan mount table
146       if ( (mfp = fopen(MNTTAB, "r")) == NULL )
147           continue;
148       mnt = &sysvmnt;
149       while ((getmntent(mfp, mnt)) >= 0) {
150         len = preflen(realPath, mnt->mnt_mountp);
151         if (len >= fsTypeLen) {
152           fsTypeLen = len;
153           (void) strncpy(
154                         fsType,
155                         mnt->mnt_fstype ? mnt->mnt_fstype : "unknown-fstype",
156                         MAXPATHLEN-1);
157         }
158       }
159       fclose(mfp);
160       break;
161
162     default:                    // run out of major options
163       if (statvfs_successful)   // if statvfs successful, infer results
164         return(statbuf.f_files == -1 ? Dtm_FL_REMOTE : Dtm_FL_LOCAL);
165       return(Dtm_FL_UNKNOWN);
166     }
167
168     // At this point, if fsTypeLen > 0 then we have found a match.
169     // Return the proper Dtm_FL_xxx code according to the type of file system
170     // path object is located on
171     //
172     if (fsTypeLen == 0)                 // nothing found??
173       continue;                         // nope - try next pass
174     if (!strcmp(fsType, "cachefs"))     // cached from anonymous source?
175       return(Dtm_FL_LOCAL_AND_REMOTE);  // yes: file is local and remote
176     else if (!strcmp(fsType, "nfs"))    // nfs resource?
177       return (Dtm_FL_REMOTE);           // yes: file is remote only
178     else if (!strcmp(fsType, "ufs"))    // ufs type file system?
179       return (Dtm_FL_LOCAL);            // yes: file is local only
180     else if (!strcmp(fsType, "tmpfs"))  // tmpfs local but transient file?
181       return (Dtm_FL_LOCAL);            // yes: file is local
182     else if (!strcmp(fsType, "autofs")) // automounter mounting point??
183       return (Dtm_FL_REMOTE);           // yes: file is remote
184
185     // no type that we recognize - try next pass
186     //
187   }
188 #else
189   int len = (int) strlen(path);
190   return(Dtm_FL_UNKNOWN);
191 #endif
192 }