2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: tt_file_system.C /main/5 1998/03/19 18:59:48 mgreess $
28 //%% restrictions in a confidential disclosure agreement between
29 //%% HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
30 //%% document outside HP, IBM, Sun, USL, SCO, or Univel without
31 //%% Sun's specific written approval. This document and all copies
32 //%% and derivative works thereof must be returned or destroyed at
35 //%% Copyright 1993, 1994 Sun Microsystems, Inc. All rights reserved.
37 /* @(#)tt_file_system.C 1.40 95/01/06
41 * Copyright (c) 1990, 1994 by Sun Microsystems, Inc.
43 * Defines a class for browsing the file system mount table.
50 #if defined(__linux__)
51 # include <sys/poll.h>
57 #include "tt_options.h"
58 #include "util/tt_port.h"
59 #include "util/tt_host_equiv.h"
61 #if defined(OPT_SVR4_GETMNTENT)
62 # include <sys/mnttab.h>
63 # include <sys/mntent.h>
64 # define TtMntTab MNTTAB
65 # define TtMntEntry struct mnttab
66 # define ttOpenMntTbl(path,mode) fopen(path,mode)
67 # define ttFsType(e) (e).mnt_fstype
68 # define ttFsName(e) (e).mnt_special
69 # define ttMountPt(e) (e).mnt_mountp
70 # define ttCloseMntTbl(f) fclose(f)
72 extern "C" int mntctl(int,int,char *);
74 # define MNTTYPE_NFS "nfs"
75 # define ttOpenMntTbl(path,mode) ((FILE *) 1)
76 # define TtMntEntry struct vmount *
77 # define ttFsType(e) \
78 (((e)->vmt_gfstype == MNT_JFS) ? "jfs" \
79 : (((e)->vmt_gfstype == MNT_NFS) ? "nfs" \
80 : (((e)->vmt_gfstype == MNT_CDROM) ? "cdrom" \
81 : (((e)->vmt_gfstype == MNT_AIX) ? "oaix" \
83 # define ttFsName(e) vmt2dataptr(e,VMT_OBJECT)
84 # define ttMountPt(e) vmt2dataptr(e,VMT_STUB)
85 # define ttCloseMntTbl(f) free(tmpbuf)
86 #elif defined(CSRG_BASED)
87 # include <sys/types.h>
88 # include <sys/mount.h>
91 #if defined(HAS_STATVFS)
92 extern "C" int getfsstat(struct statvfs *, long, int);
95 # define MNTTYPE_NFS "nfs"
96 # define ttOpenMntTbl(path,mode) ((FILE *) 1)
98 # if defined(HAS_STATVFS)
99 # include <sys/statvfs.h>
100 # define TtMntEntry struct statvfs *
102 # define TtMntEntry struct statfs *
105 # if defined(CSRG_BASED)
106 # define ttFsType(e) (e->f_fstypename)
108 # define ttFsName(e) ((char *)((e)->f_mntfromname))
109 # define ttMountPt(e) ((char *)((e)->f_mntonname))
110 # define ttCloseMntTbl(f) free(buf)
113 # define TtMntTab MOUNTED
114 # define MNTTYPE_RFS "rfs"
115 # define TtMntEntry struct mntent *
116 # define ttOpenMntTbl(path,mode) setmntent(path,mode)
117 # define ttFsType(e) (e)->mnt_type
118 # define ttFsName(e) (e)->mnt_fsname
119 # define ttMountPt(e) (e)->mnt_dir
120 # define ttCloseMntTbl(f) endmntent(f)
122 #include "util/tt_file_system_entry_utils.h"
123 #include "util/tt_file_system.h"
124 #include "util/tt_file_system_entry.h"
125 #include "util/tt_path.h"
126 #include "util/tt_port.h"
127 #include "util/tt_host.h"
128 #include "util/tt_global_env.h"
130 #if defined(OPT_BUG_SUNOS_5)
131 // Bug 1116904 filed on the absence of hasmntopt from the
132 // header file. Fixed in SunOS 5.3, but we leave this in so
133 // we can compile on 5.1 and 5.2.
135 extern char *hasmntopt(struct mnttab *mnt, char *opt);
139 time_t _Tt_file_system::lastMountTime = 0;
144 // It would be simpler just to have a static instance of
145 // _Tt_file_system_entry_list here, but static class instances
146 // are verboten if we want to be called by C programs.
147 if (_tt_global->fileSystemEntries.is_null()) {
148 _tt_global->fileSystemEntries = new _Tt_file_system_entry_list;
159 static _Tt_file_system_entry *
160 createFileSystemEntry(TtMntEntry entry)
163 _Tt_string mount_point;
164 _Tt_string partition;
166 int loop_back_flag = 0;
168 // not all platforms have the IGNORE option, but if it
169 // is defined, be sure to ignore mount entries with it
170 // set, as they are things like automounter entries
171 // that will just confuse the mapping.
173 #if defined(MNTOPT_IGNORE)
174 if (0!=hasmntopt(&entry, MNTOPT_IGNORE)) {
175 return (_Tt_file_system_entry *)0;
178 if ( (strcmp( ttFsType(entry), MNTTYPE_NFS) == 0)
179 #if defined(MNTTYPE_RFS)
180 || (strcmp( ttFsType(entry), MNTTYPE_RFS) == 0)
185 // AIX is different; at least it\'s arguably better.
186 hostname = vmt2dataptr(entry,VMT_HOSTNAME);
187 partition = ttFsName(entry);
190 // Search for a '.' to separate the hostname and
192 char *endOfHostNamePos =
193 strchr(ttFsName(entry), '.');
195 // Search for the ':' that separates the
196 // hostname and the rest of the mtab field.
198 char *justBeforePartitionPos =
199 strchr(ttFsName(entry), ':');
201 // If there was no domain name or the dot
202 // found above was after the ':' (the dot was
203 // just part of a directoty name), then the
204 // hostname ends at the ':' position.
206 if (!endOfHostNamePos ||
207 (justBeforePartitionPos < endOfHostNamePos)) {
208 endOfHostNamePos = justBeforePartitionPos;
211 // NULL terminate the hostname part of the field
212 if (endOfHostNamePos) {
213 *endOfHostNamePos = '\0';
216 if (justBeforePartitionPos) {
217 partition = justBeforePartitionPos+1;
220 hostname = ttFsName(entry);
223 loop_back_flag = FALSE;
225 partition = ttFsName(entry);
226 _Tt_host_ptr localHost;
227 _tt_global->get_local_host( localHost );
228 hostname = localHost->name();
230 loop_back_flag = FALSE;
232 #if defined(MNTTYPE_LOFS)
233 if (!strcmp( ttFsType(entry), MNTTYPE_LOFS)) {
234 loop_back_flag = TRUE;
238 mount_point = ttMountPt(entry);
240 return new _Tt_file_system_entry( hostname, mount_point, partition,
241 local_flag, loop_back_flag );
246 * Finds the best match mount table entry to the specified local path
247 * resolving loop back mounts to the true mount point.
249 _Tt_file_system_entry_ptr _Tt_file_system::
250 bestMatchToPath (const _Tt_string &path)
252 _Tt_string real_path = _tt_realpath(path);
254 updateFileSystemEntries();
256 _Tt_file_system_entry_ptr max_match_entry;
257 bool_t loop_back_flag = TRUE;
258 _Tt_string current_loop_back_mount_point;
259 _Tt_string first_loop_back_mount_point;
260 bool_t first_time = TRUE;
262 while (loop_back_flag) {
263 max_match_entry = findBestMountPoint(real_path,
265 current_loop_back_mount_point);
267 if (loop_back_flag && first_time) {
268 first_loop_back_mount_point =
269 current_loop_back_mount_point;
275 max_match_entry->loopBackMountPoint = first_loop_back_mount_point;
276 return max_match_entry;
280 * Finds the best matching mount pount to the specified local path.
281 * If the best match is a loop back then the matching portion of the
282 * specified path is updated to the loop back partition and the loop
283 * back flag parameter is set to TRUE.
285 _Tt_file_system_entry_ptr _Tt_file_system::
286 findBestMountPoint (_Tt_string &path,
287 bool_t &loop_back_flag,
288 _Tt_string &loop_back_mount_point)
290 updateFileSystemEntries();
292 _Tt_string current_mount_point;
293 int current_mount_point_length;
294 _Tt_file_system_entry_ptr max_match_entry;
295 int max_match_length = 0;
296 int path_length = path.len();
298 _Tt_file_system_entry_list_cursor
299 entries_cursor(_tt_global->fileSystemEntries);
301 while (entries_cursor.next()) {
302 current_mount_point = entries_cursor->getMountPoint();
303 current_mount_point_length = current_mount_point.len();
304 if (path_length < current_mount_point_length) {
308 if (current_mount_point_length > max_match_length) {
309 if (!memcmp((char *)current_mount_point,
311 current_mount_point_length)) {
312 max_match_length = current_mount_point_length;
313 max_match_entry = *entries_cursor;
317 if (max_match_length == path_length) {
322 if (max_match_entry->isLoopBack ()) {
323 loop_back_flag = TRUE;
325 _Tt_string mount_point = max_match_entry->getMountPoint();
326 _Tt_string partition = max_match_entry->getPartition();
328 // Get the path info after the mount point path
329 path = path.right(path.len()-mount_point.len());
331 // Prepend the loop back partition onto the rest of the path
332 path = partition.cat(path);
334 // Return the loop back mount point
335 loop_back_mount_point = mount_point;
337 loop_back_flag = FALSE;
340 return max_match_entry;
344 * Finds the mount table entry corresponding to the specified network path.
345 * The specified path must be of the form:
349 _Tt_file_system_entry_ptr _Tt_file_system::
350 findMountEntry (const _Tt_string &network_path)
352 updateFileSystemEntries();
354 _Tt_string current_hostname;
355 _Tt_string current_partition;
356 int current_partition_length;
357 _Tt_file_system_entry_ptr entry;
363 path = path.split(':', hostname);
365 int path_length = path.len();
367 _Tt_file_system_entry_list_cursor
368 entries_cursor(_tt_global->fileSystemEntries);
370 _Tt_host_equiv_ptr eq_p = new _Tt_host_equiv();
371 while (entries_cursor.next()) {
372 current_hostname = entries_cursor->getHostname();
374 if (eq_p->hostname_equiv(hostname, current_hostname) == 1) {
375 current_partition = entries_cursor->getPartition();
376 current_partition_length = current_partition.len();
378 if (path_length >= current_partition_length) {
379 if (!memcmp((char *)path, (char *)current_partition,
380 current_partition_length)) {
381 entry = *entries_cursor;
390 void _Tt_file_system::
391 updateFileSystemEntries ()
393 static int firsttime = 1;
394 static int since_last = 0;
397 if (since_last < _tt_global->event_counter) {
398 since_last = _tt_global->event_counter;
404 // AIX doesn\'t have a mount table file as such.
407 struct stat mount_table_stat;
408 if (stat(TtMntTab, &mount_table_stat)) {
412 if (!firsttime && mount_table_stat.st_mtime <= lastMountTime) {
418 // XXX Due to bug #1126575 - MNTTAB temporarily goes to
419 // size 0 during automounter updates. The file stats
420 // OK, but has no data in it.
421 struct pollfd poll_fd;
422 while (mount_table_stat.st_size == 0) {
423 (void)poll (&poll_fd, 0, 100);
424 // Must use lstat here; mtab is often a symlink
425 if (lstat(TtMntTab, &mount_table_stat)) {
430 FILE *mount_table = ttOpenMntTbl(TtMntTab, "r");
435 fcntl(fileno(mount_table), F_SETFD, 1); // Close on exec.
437 lastMountTime = mount_table_stat.st_mtime;
440 _tt_global->fileSystemEntries->flush();
441 _Tt_file_system_entry_ptr fse;
445 char *tmpbuf = (char *)malloc( sz );
447 while ((rc = mntctl(MCTL_QUERY, sz, tmpbuf)) == 0)
449 // increase buffer size
450 sz = *((int *) tmpbuf);
452 tmpbuf = (char *)malloc( sz );
455 for (entry = (TtMntEntry)tmpbuf; rc > 0; --rc,
456 entry = (TtMntEntry)((char *) entry + entry->vmt_length))
458 #elif defined(HAS_STATVFS)
462 int flags = MNT_NOWAIT;
463 char *s, *host, path[MNAMELEN] ;
465 numfs = getvfsstat ( (struct statvfs *)0, 0, 0 );
467 bufsize = numfs * sizeof ( struct statvfs );
468 buf = (struct statvfs *) malloc ( bufsize );
469 memset ((void *)buf,0,bufsize);
471 getvfsstat ( buf, bufsize, flags );
473 for ( i=0; i<numfs; i++ )
475 // convert path@host to host:/path
476 s = strchr(buf[i].f_mntfromname,'@');
479 memset((char*)path,0,MNAMELEN);
480 strncpy(path,buf[i].f_mntfromname, (strlen(buf[i].f_mntfromname)
482 strcpy(buf[i].f_mntfromname,host) ;
483 strcat(buf[i].f_mntfromname,":") ;
484 strcat(buf[i].f_mntfromname,path) ;
488 #elif defined(CSRG_BASED)
492 int flags = MNT_NOWAIT;
493 char *s, *host, path[MNAMELEN] ;
495 numfs = getfsstat ( (struct statfs *)0, 0, flags );
497 _tt_syslog(0,LOG_ERR,"getfsstat: %s",strerror(errno));
500 bufsize = numfs * sizeof ( struct statfs );
501 buf = (struct statfs *) malloc ( bufsize );
502 memset ((void *)buf,0,bufsize);
504 getfsstat ( buf, bufsize, flags );
506 for ( i=0; i<numfs; i++ )
508 // convert path@host to host:/path
509 s = strchr(buf[i].f_mntfromname,'@');
512 memset((char*)path,0,MNAMELEN);
513 strncpy(path,buf[i].f_mntfromname, (strlen(buf[i].f_mntfromname)
515 strcpy(buf[i].f_mntfromname,host) ;
516 strcat(buf[i].f_mntfromname,":") ;
517 strcat(buf[i].f_mntfromname,path) ;
521 #elif defined(OPT_SVR4_GETMNTENT)
523 while (! (rc = getmntent(mount_table, &entry)))
525 while (entry = getmntent(mount_table))
527 #if !defined(CSRG_BASED)
530 fse = createFileSystemEntry( entry );
531 if (!fse.is_null()) {
532 #if defined(TT_DEBUG_FNM)
533 fprintf(stderr,"File name mapping: %s:%s on %s; %s %s\n",
534 (char *)fse->getHostname(),
535 (char *)fse->getPartition(),
536 (char *)fse->getMountPoint(),
537 fse->isLocal()?"local":"",
538 fse->isLoopBack()?"loopback":"");
540 _tt_global->fileSystemEntries->append(fse);
544 ttCloseMntTbl(mount_table);
547 void _Tt_file_system::
550 if (!_tt_global->fileSystemEntries.is_null()) {
551 _tt_global->fileSystemEntries->flush();
556 /* Local Variables : */
557 /* c++-indent-level: 2 */