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 librararies 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 # include <sys/poll.h>
56 #include "tt_options.h"
57 #include "util/tt_port.h"
58 #include "util/tt_host_equiv.h"
60 #if defined(OPT_SVR4_GETMNTENT)
61 # include <sys/mnttab.h>
62 # include <sys/mntent.h>
63 # define TtMntTab MNTTAB
64 # define TtMntEntry struct mnttab
65 # define ttOpenMntTbl(path,mode) fopen(path,mode)
66 # define ttFsType(e) (e).mnt_fstype
67 # define ttFsName(e) (e).mnt_special
68 # define ttMountPt(e) (e).mnt_mountp
69 # define ttCloseMntTbl(f) fclose(f)
71 extern "C" int mntctl(int,int,char *);
73 # define MNTTYPE_NFS "nfs"
74 # define ttOpenMntTbl(path,mode) ((FILE *) 1)
75 # define TtMntEntry struct vmount *
76 # define ttFsType(e) \
77 (((e)->vmt_gfstype == MNT_JFS) ? "jfs" \
78 : (((e)->vmt_gfstype == MNT_NFS) ? "nfs" \
79 : (((e)->vmt_gfstype == MNT_CDROM) ? "cdrom" \
80 : (((e)->vmt_gfstype == MNT_AIX) ? "oaix" \
82 # define ttFsName(e) vmt2dataptr(e,VMT_OBJECT)
83 # define ttMountPt(e) vmt2dataptr(e,VMT_STUB)
84 # define ttCloseMntTbl(f) free(tmpbuf)
85 #elif defined(__osf__) || defined(CSRG_BASED)
86 # include <sys/types.h>
87 # include <sys/mount.h>
89 extern "C" int getfsstat(struct statfs *, long, int);
91 # define MNTTYPE_NFS "nfs"
92 # define ttOpenMntTbl(path,mode) ((FILE *) 1)
93 # define TtMntEntry struct statfs *
95 # define ttFsType(e) \
96 (((e)->f_type == MOUNT_UFS) ? "ufs" \
97 : (((e)->f_type == MOUNT_NFS3) ? "nfs" \
98 : (((e)->f_type == MOUNT_NFS) ? "nfs" \
99 : (((e)->f_type == MOUNT_CDFS) ? "cdfs" \
100 : (((e)->f_type == MOUNT_PROCFS) ? "procfs" \
102 # elif defined(CSRG_BASED)
103 # define ttFsType(e) (e->f_fstypename)
105 # define ttFsName(e) ((char *)((e)->f_mntfromname))
106 # define ttMountPt(e) ((char *)((e)->f_mntonname))
107 # define ttCloseMntTbl(f) free(buf)
110 # define TtMntTab MOUNTED
111 # define MNTTYPE_RFS "rfs"
112 # define TtMntEntry struct mntent *
113 # define ttOpenMntTbl(path,mode) setmntent(path,mode)
114 # define ttFsType(e) (e)->mnt_type
115 # define ttFsName(e) (e)->mnt_fsname
116 # define ttMountPt(e) (e)->mnt_dir
117 # define ttCloseMntTbl(f) endmntent(f)
119 #include "util/tt_file_system_entry_utils.h"
120 #include "util/tt_file_system.h"
121 #include "util/tt_file_system_entry.h"
122 #include "util/tt_path.h"
123 #include "util/tt_port.h"
124 #include "util/tt_host.h"
125 #include "util/tt_global_env.h"
127 #if defined(OPT_BUG_SUNOS_5)
128 // Bug 1116904 filed on the absence of hasmntopt from the
129 // header file. Fixed in SunOS 5.3, but we leave this in so
130 // we can compile on 5.1 and 5.2.
132 extern char *hasmntopt(struct mnttab *mnt, char *opt);
136 time_t _Tt_file_system::lastMountTime = 0;
141 // It would be simpler just to have a static instance of
142 // _Tt_file_system_entry_list here, but static class instances
143 // are verboten if we want to be called by C programs.
144 if (_tt_global->fileSystemEntries.is_null()) {
145 _tt_global->fileSystemEntries = new _Tt_file_system_entry_list;
156 static _Tt_file_system_entry *
157 createFileSystemEntry(TtMntEntry entry)
160 _Tt_string mount_point;
161 _Tt_string partition;
163 int loop_back_flag = 0;
165 // not all platforms have the IGNORE option, but if it
166 // is defined, be sure to ignore mount entries with it
167 // set, as they are things like automounter entries
168 // that will just confuse the mapping.
170 #if defined(MNTOPT_IGNORE)
171 if (0!=hasmntopt(&entry, MNTOPT_IGNORE)) {
172 return (_Tt_file_system_entry *)0;
175 if ( (strcmp( ttFsType(entry), MNTTYPE_NFS) == 0)
176 #if defined(MNTTYPE_RFS)
177 || (strcmp( ttFsType(entry), MNTTYPE_RFS) == 0)
182 // AIX is different; at least it\'s arguably better.
183 hostname = vmt2dataptr(entry,VMT_HOSTNAME);
184 partition = ttFsName(entry);
187 // Search for a '.' to separate the hostname and
189 char *endOfHostNamePos =
190 strchr(ttFsName(entry), '.');
192 // Search for the ':' that separates the
193 // hostname and the rest of the mtab field.
195 char *justBeforePartitionPos =
196 strchr(ttFsName(entry), ':');
198 // If there was no domain name or the dot
199 // found above was after the ':' (the dot was
200 // just part of a directoty name), then the
201 // hostname ends at the ':' position.
203 if (!endOfHostNamePos ||
204 (justBeforePartitionPos < endOfHostNamePos)) {
205 endOfHostNamePos = justBeforePartitionPos;
208 // NULL terminate the hostname part of the field
209 if (endOfHostNamePos) {
210 *endOfHostNamePos = '\0';
213 if (justBeforePartitionPos) {
214 partition = justBeforePartitionPos+1;
217 hostname = ttFsName(entry);
220 loop_back_flag = FALSE;
222 partition = ttFsName(entry);
223 _Tt_host_ptr localHost;
224 _tt_global->get_local_host( localHost );
225 hostname = localHost->name();
227 loop_back_flag = FALSE;
229 #if defined(MNTTYPE_LOFS)
230 if (!strcmp( ttFsType(entry), MNTTYPE_LOFS)) {
231 loop_back_flag = TRUE;
235 mount_point = ttMountPt(entry);
237 return new _Tt_file_system_entry( hostname, mount_point, partition,
238 local_flag, loop_back_flag );
243 * Finds the best match mount table entry to the specified local path
244 * resolving loop back mounts to the true mount point.
246 _Tt_file_system_entry_ptr _Tt_file_system::
247 bestMatchToPath (const _Tt_string &path)
249 _Tt_string real_path = _tt_realpath(path);
251 updateFileSystemEntries();
253 _Tt_file_system_entry_ptr max_match_entry;
254 bool_t loop_back_flag = TRUE;
255 _Tt_string current_loop_back_mount_point;
256 _Tt_string first_loop_back_mount_point;
257 bool_t first_time = TRUE;
259 while (loop_back_flag) {
260 max_match_entry = findBestMountPoint(real_path,
262 current_loop_back_mount_point);
264 if (loop_back_flag && first_time) {
265 first_loop_back_mount_point =
266 current_loop_back_mount_point;
272 max_match_entry->loopBackMountPoint = first_loop_back_mount_point;
273 return max_match_entry;
277 * Finds the best matching mount pount to the specified local path.
278 * If the best match is a loop back then the matching portion of the
279 * specified path is updated to the loop back partition and the loop
280 * back flag parameter is set to TRUE.
282 _Tt_file_system_entry_ptr _Tt_file_system::
283 findBestMountPoint (_Tt_string &path,
284 bool_t &loop_back_flag,
285 _Tt_string &loop_back_mount_point)
287 updateFileSystemEntries();
289 _Tt_string current_mount_point;
290 int current_mount_point_length;
291 _Tt_file_system_entry_ptr max_match_entry;
292 int max_match_length = 0;
293 int path_length = path.len();
295 _Tt_file_system_entry_list_cursor
296 entries_cursor(_tt_global->fileSystemEntries);
298 while (entries_cursor.next()) {
299 current_mount_point = entries_cursor->getMountPoint();
300 current_mount_point_length = current_mount_point.len();
301 if (path_length < current_mount_point_length) {
305 if (current_mount_point_length > max_match_length) {
306 if (!memcmp((char *)current_mount_point,
308 current_mount_point_length)) {
309 max_match_length = current_mount_point_length;
310 max_match_entry = *entries_cursor;
314 if (max_match_length == path_length) {
319 if (max_match_entry->isLoopBack ()) {
320 loop_back_flag = TRUE;
322 _Tt_string mount_point = max_match_entry->getMountPoint();
323 _Tt_string partition = max_match_entry->getPartition();
325 // Get the path info after the mount point path
326 path = path.right(path.len()-mount_point.len());
328 // Prepend the loop back partition onto the rest of the path
329 path = partition.cat(path);
331 // Return the loop back mount point
332 loop_back_mount_point = mount_point;
334 loop_back_flag = FALSE;
337 return max_match_entry;
341 * Finds the mount table entry corresponding to the specified network path.
342 * The specified path must be of the form:
346 _Tt_file_system_entry_ptr _Tt_file_system::
347 findMountEntry (const _Tt_string &network_path)
349 updateFileSystemEntries();
351 _Tt_string current_hostname;
352 _Tt_string current_partition;
353 int current_partition_length;
354 _Tt_file_system_entry_ptr entry;
360 path = path.split(':', hostname);
362 int path_length = path.len();
364 _Tt_file_system_entry_list_cursor
365 entries_cursor(_tt_global->fileSystemEntries);
367 _Tt_host_equiv_ptr eq_p = new _Tt_host_equiv();
368 while (entries_cursor.next()) {
369 current_hostname = entries_cursor->getHostname();
372 printf("DEBUG findMountEntry: hostname = %s, current_hostname = %s\n",
373 (char *) hostname, (char *) current_hostname);
376 if (eq_p->hostname_equiv(hostname, current_hostname) == 1) {
377 current_partition = entries_cursor->getPartition();
378 current_partition_length = current_partition.len();
381 printf("DEBUG findMountEntry: found hostname equivalence between %s and %s\n",
382 (char *) hostname, (char *) current_hostname);
385 if (path_length >= current_partition_length) {
386 if (!memcmp((char *)path, (char *)current_partition,
387 current_partition_length)) {
388 entry = *entries_cursor;
390 printf("DEBUG findMountEntry: found PATH equivalence between %s and %s\n",
391 (char *) hostname, (char *) current_hostname);
402 void _Tt_file_system::
403 updateFileSystemEntries ()
405 static int firsttime = 1;
406 static int since_last = 0;
409 if (since_last < _tt_global->event_counter) {
410 since_last = _tt_global->event_counter;
416 // AIX doesn\'t have a mount table file as such.
419 struct stat mount_table_stat;
420 if (stat(TtMntTab, &mount_table_stat)) {
424 if (!firsttime && mount_table_stat.st_mtime <= lastMountTime) {
430 // XXX Due to bug #1126575 - MNTTAB temporarily goes to
431 // size 0 during automounter updates. The file stats
432 // OK, but has no data in it.
434 while (mount_table_stat.st_size == 0) {
435 (void)poll (&poll_fd, 0, 100);
436 // Must use lstat here; mtab is often a symlink
437 if (lstat(TtMntTab, &mount_table_stat)) {
442 FILE *mount_table = ttOpenMntTbl(TtMntTab, "r");
447 fcntl(fileno(mount_table), F_SETFD, 1); // Close on exec.
449 lastMountTime = mount_table_stat.st_mtime;
452 _tt_global->fileSystemEntries->flush();
453 _Tt_file_system_entry_ptr fse;
457 char *tmpbuf = (char *)malloc( sz );
459 while ((rc = mntctl(MCTL_QUERY, sz, tmpbuf)) == 0)
461 // increase buffer size
462 sz = *((int *) tmpbuf);
464 tmpbuf = (char *)malloc( sz );
467 for (entry = (TtMntEntry)tmpbuf; rc > 0; --rc,
468 entry = (TtMntEntry)((char *) entry + entry->vmt_length))
469 #elif defined(__osf__) || defined(CSRG_BASED)
473 int flags = MNT_NOWAIT;
474 char *s, *host, path[MNAMELEN] ;
476 numfs = getfsstat ( (struct statfs *)0, 0, 0 );
478 bufsize = numfs * sizeof ( struct statfs );
479 buf = (struct statfs *) malloc ( bufsize );
480 memset ((void *)buf,0,bufsize);
482 getfsstat ( buf, bufsize, flags );
484 for ( i=0; i<numfs; i++ )
486 // convert path@host to host:/path
487 s = strchr(buf[i].f_mntfromname,'@');
490 memset((char*)path,0,MNAMELEN);
491 strncpy(path,buf[i].f_mntfromname, (strlen(buf[i].f_mntfromname)
493 strcpy(buf[i].f_mntfromname,host) ;
494 strcat(buf[i].f_mntfromname,":") ;
495 strcat(buf[i].f_mntfromname,path) ;
499 #elif defined(OPT_SVR4_GETMNTENT)
501 while (! (rc = getmntent(mount_table, &entry)))
503 while (entry = getmntent(mount_table))
505 #if !defined(__osf__) && !defined(CSRG_BASED)
508 fse = createFileSystemEntry( entry );
509 if (!fse.is_null()) {
510 #if defined(TT_DEBUG_FNM)
511 fprintf(stderr,"File name mapping: %s:%s on %s; %s %s\n",
512 (char *)fse->getHostname(),
513 (char *)fse->getPartition(),
514 (char *)fse->getMountPoint(),
515 fse->isLocal()?"local":"",
516 fse->isLoopBack()?"loopback":"");
518 _tt_global->fileSystemEntries->append(fse);
522 ttCloseMntTbl(mount_table);
525 void _Tt_file_system::
528 if (!_tt_global->fileSystemEntries.is_null()) {
529 _tt_global->fileSystemEntries->flush();
534 /* Local Variables : */
535 /* c++-indent-level: 2 */