Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / tt / lib / util / tt_file_system.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 libraries 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 //%%  (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   
33 //%%    Sun's request.                                                  
34 //%%                                                                    
35 //%%    Copyright 1993, 1994 Sun Microsystems, Inc.  All rights reserved.       
36 //%%                                                                    
37 /* @(#)tt_file_system.C 1.40 95/01/06
38  *
39  * Tool Talk Utility
40  *
41  * Copyright (c) 1990, 1994 by Sun Microsystems, Inc.
42  *
43  * Defines a class for browsing the file system mount table.
44  *
45  */
46
47 #include <stdio.h>
48 #include <string.h>
49 #include <errno.h>
50 #if defined(__linux__)
51 # include <sys/poll.h>
52 #else
53 # include <poll.h>
54 #endif
55 #include <sys/stat.h>
56 #include <fcntl.h>
57 #include "tt_options.h"
58 #include "util/tt_port.h"
59 #include "util/tt_host_equiv.h"
60
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)
71 #elif defined(_AIX)
72         extern "C" int mntctl(int,int,char *);
73 #       include <sys/vfs.h>
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" \
82                                    : "unknown"))))
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>
89
90
91 #if defined(HAS_STATVFS)
92         extern "C" int getfsstat(struct statvfs *, long, int);
93 # endif
94
95 #       define MNTTYPE_NFS              "nfs"
96 #       define ttOpenMntTbl(path,mode)  ((FILE *) 1)
97
98 # if defined(HAS_STATVFS)
99 #     include <sys/statvfs.h>
100 #     define TtMntEntry struct statvfs *
101 # else
102 #     define TtMntEntry struct statfs *
103 # endif
104
105 # if defined(CSRG_BASED)
106 #       define ttFsType(e)              (e->f_fstypename)
107 # endif
108 #       define ttFsName(e)              ((char *)((e)->f_mntfromname))
109 #       define ttMountPt(e)             ((char *)((e)->f_mntonname))
110 #       define ttCloseMntTbl(f)         free(buf)
111 #else
112 #       include <mntent.h>
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)
121 #endif
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"
129
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.
134 extern "C" {
135         extern char *hasmntopt(struct mnttab *mnt, char *opt);
136 };
137 #endif
138
139 time_t                          _Tt_file_system::lastMountTime          = 0;
140
141 _Tt_file_system::
142 _Tt_file_system ()
143 {
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;
149                 lastMountTime = 0;
150         }
151 }
152
153 _Tt_file_system::
154 ~_Tt_file_system ()
155 {
156         lastMountTime = 0;
157 }
158
159 static _Tt_file_system_entry *
160 createFileSystemEntry(TtMntEntry entry)
161 {
162         _Tt_string hostname;
163         _Tt_string mount_point;
164         _Tt_string partition;
165         int        local_flag = 1;
166         int        loop_back_flag = 0;
167         //
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.
172         //
173 #if defined(MNTOPT_IGNORE)
174         if (0!=hasmntopt(&entry, MNTOPT_IGNORE)) {
175                 return (_Tt_file_system_entry *)0;
176         }
177 #endif
178         if (   (strcmp( ttFsType(entry), MNTTYPE_NFS) == 0)
179 #if defined(MNTTYPE_RFS)
180             || (strcmp( ttFsType(entry), MNTTYPE_RFS) == 0)
181 #endif
182            )
183         {
184 #if defined(_AIX)
185                 // AIX is different; at least it\'s arguably better.
186                 hostname = vmt2dataptr(entry,VMT_HOSTNAME);
187                 partition = ttFsName(entry);
188 #else /* AIX */
189         
190                 // Search for a '.' to separate the hostname and
191                 // the domain name
192                 char *endOfHostNamePos =
193                         strchr(ttFsName(entry), '.');
194
195                 // Search for the ':' that separates the
196                 // hostname and the rest of the mtab field.
197
198                 char *justBeforePartitionPos =
199                         strchr(ttFsName(entry), ':');
200
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.
205
206                 if (!endOfHostNamePos ||
207                     (justBeforePartitionPos < endOfHostNamePos)) {
208                         endOfHostNamePos = justBeforePartitionPos;
209                 }
210
211                 // NULL terminate the hostname part of the field
212                 if (endOfHostNamePos) {
213                         *endOfHostNamePos = '\0';
214                 }
215
216                 if (justBeforePartitionPos) {
217                         partition = justBeforePartitionPos+1;
218                 }
219
220                 hostname = ttFsName(entry);
221 #endif  /* AIX */       
222                 local_flag = FALSE;
223                 loop_back_flag = FALSE;
224         } else {
225                 partition = ttFsName(entry);
226                 _Tt_host_ptr localHost;
227                 _tt_global->get_local_host( localHost );
228                 hostname = localHost->name();
229                 local_flag = TRUE;
230                 loop_back_flag = FALSE;
231
232 #if defined(MNTTYPE_LOFS)
233                 if (!strcmp( ttFsType(entry), MNTTYPE_LOFS)) {
234                         loop_back_flag = TRUE;
235                 }
236 #endif
237         }
238         mount_point = ttMountPt(entry);
239
240         return new _Tt_file_system_entry( hostname, mount_point, partition,
241                                           local_flag, loop_back_flag );
242 }
243
244
245 /*
246  * Finds the best match mount table entry to the specified local path
247  * resolving loop back mounts to the true mount point.
248  */
249 _Tt_file_system_entry_ptr _Tt_file_system::
250 bestMatchToPath (const _Tt_string &path)
251 {
252         _Tt_string real_path = _tt_realpath(path);
253
254         updateFileSystemEntries();
255
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;
261
262         while (loop_back_flag) {
263                 max_match_entry = findBestMountPoint(real_path,
264                                                   loop_back_flag,
265                                                   current_loop_back_mount_point);
266
267                 if (loop_back_flag && first_time) {
268                         first_loop_back_mount_point =
269                                 current_loop_back_mount_point;
270                 }
271
272                 first_time = FALSE;
273         }
274
275         max_match_entry->loopBackMountPoint = first_loop_back_mount_point;
276         return max_match_entry;
277 }
278
279 /*
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.
284  */
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)
289 {
290         updateFileSystemEntries();
291
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();
297
298         _Tt_file_system_entry_list_cursor
299                 entries_cursor(_tt_global->fileSystemEntries);
300
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) {
305                         continue;
306                 }
307
308                 if (current_mount_point_length > max_match_length) {
309                         if (!memcmp((char *)current_mount_point,
310                                     (char *)path,
311                                     current_mount_point_length)) {
312                                 max_match_length = current_mount_point_length;
313                                 max_match_entry = *entries_cursor;
314                         }  
315                 }
316
317                 if (max_match_length == path_length) {
318                         break;
319                 }
320         }
321
322         if (max_match_entry->isLoopBack ()) {
323                 loop_back_flag = TRUE;
324
325                 _Tt_string mount_point = max_match_entry->getMountPoint();
326                 _Tt_string partition = max_match_entry->getPartition();
327
328                 // Get the path info after the mount point path
329                 path = path.right(path.len()-mount_point.len());
330
331                 // Prepend the loop back partition onto the rest of the path
332                 path = partition.cat(path);
333
334                 // Return the loop back mount point
335                 loop_back_mount_point = mount_point;
336         } else {
337                 loop_back_flag = FALSE;
338         }
339
340         return max_match_entry;
341 }
342
343 /*
344  * Finds the mount table entry corresponding to the specified network path.
345  * The specified path must be of the form:
346  *
347  *              hostname:/path
348  */
349 _Tt_file_system_entry_ptr _Tt_file_system::
350 findMountEntry (const _Tt_string &network_path)
351 {
352         updateFileSystemEntries();
353
354         _Tt_string                      current_hostname;
355         _Tt_string                      current_partition;
356         int                             current_partition_length;
357         _Tt_file_system_entry_ptr       entry;
358
359         _Tt_string hostname;
360         _Tt_string path;
361
362         path = network_path;
363         path = path.split(':', hostname);
364
365         int path_length = path.len();
366
367         _Tt_file_system_entry_list_cursor
368                 entries_cursor(_tt_global->fileSystemEntries);
369
370         _Tt_host_equiv_ptr eq_p = new _Tt_host_equiv();
371         while (entries_cursor.next()) {
372                 current_hostname = entries_cursor->getHostname();
373
374                 if (eq_p->hostname_equiv(hostname, current_hostname) == 1) {
375                         current_partition = entries_cursor->getPartition();
376                         current_partition_length = current_partition.len();
377
378                         if (path_length >= current_partition_length) {
379                                 if (!memcmp((char *)path, (char *)current_partition,
380                                             current_partition_length)) {
381                                         entry = *entries_cursor;
382                                         break;
383                                 }
384                         }
385                 }
386         }
387         return entry;
388 }
389
390 void _Tt_file_system::
391 updateFileSystemEntries ()
392 {
393         static int firsttime = 1;
394         static int since_last = 0;
395
396         if (!firsttime) {
397                 if (since_last < _tt_global->event_counter) {
398                         since_last = _tt_global->event_counter;
399                 } else {
400                         return;
401                 }
402         }
403
404 // AIX  doesn\'t have a mount table file as such.
405 #ifdef TtMntTab
406
407         struct stat mount_table_stat;
408         if (stat(TtMntTab, &mount_table_stat)) {
409                 return;
410         }
411
412         if (!firsttime && mount_table_stat.st_mtime <= lastMountTime) {
413                 return;
414         }
415
416         firsttime = 0;
417         
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)) {
426                         return;
427                 }
428         }
429
430         FILE *mount_table = ttOpenMntTbl(TtMntTab, "r");
431
432         if (! mount_table) {
433                 return;
434         }
435         fcntl(fileno(mount_table), F_SETFD, 1);         // Close on exec.
436
437         lastMountTime = mount_table_stat.st_mtime;
438 #endif
439
440         _tt_global->fileSystemEntries->flush();
441         _Tt_file_system_entry_ptr fse;  
442         TtMntEntry entry;
443 #if defined(_AIX)
444         int     rc, sz = BUFSIZ;
445         char    *tmpbuf = (char *)malloc( sz );
446
447         while ((rc = mntctl(MCTL_QUERY, sz, tmpbuf)) == 0)
448         {
449                 // increase buffer size
450                 sz = *((int *) tmpbuf);
451                 free( tmpbuf );
452                 tmpbuf = (char *)malloc( sz );
453         }
454
455         for (entry = (TtMntEntry)tmpbuf; rc > 0; --rc,
456              entry = (TtMntEntry)((char *) entry + entry->vmt_length))
457
458 #elif defined(HAS_STATVFS)
459         int             numfs,i;
460         struct statvfs  *buf;
461         long            bufsize;
462         int             flags = MNT_NOWAIT;
463         char            *s, *host, path[MNAMELEN] ;
464
465         numfs = getvfsstat ( (struct statvfs *)0, 0, 0 );
466
467         bufsize = numfs * sizeof ( struct statvfs );
468         buf = (struct statvfs *) malloc ( bufsize );
469         memset ((void *)buf,0,bufsize);
470
471         getvfsstat ( buf, bufsize, flags );
472
473         for ( i=0; i<numfs; i++ )
474         {
475             // convert path@host to host:/path
476             s = strchr(buf[i].f_mntfromname,'@');
477             if (s != NULL) {
478                 host = s + 1 ;
479                 memset((char*)path,0,MNAMELEN);
480                 strncpy(path,buf[i].f_mntfromname, (strlen(buf[i].f_mntfromname)
481  - strlen(s))) ;
482                 strcpy(buf[i].f_mntfromname,host) ;
483                 strcat(buf[i].f_mntfromname,":") ;
484                 strcat(buf[i].f_mntfromname,path) ;
485             }
486             entry = &buf[i];
487
488 #elif defined(CSRG_BASED)
489         int             numfs,i;
490         struct statfs   *buf;
491         long            bufsize;
492         int             flags = MNT_NOWAIT;
493         char            *s, *host, path[MNAMELEN] ;
494  
495         numfs = getfsstat ( (struct statfs *)0, 0, flags );
496         if(numfs == (-1)){
497             _tt_syslog(0,LOG_ERR,"getfsstat: %s",strerror(errno));
498             exit(EXIT_FAILURE);
499         }
500         bufsize = numfs * sizeof ( struct statfs );
501         buf = (struct statfs *) malloc ( bufsize );
502         memset ((void *)buf,0,bufsize);
503
504         getfsstat ( buf, bufsize, flags );
505
506         for ( i=0; i<numfs; i++ )
507         {
508             // convert path@host to host:/path
509             s = strchr(buf[i].f_mntfromname,'@');
510             if (s != NULL) {
511                 host = s + 1 ;
512                  memset((char*)path,0,MNAMELEN);
513                 strncpy(path,buf[i].f_mntfromname, (strlen(buf[i].f_mntfromname)
514  - strlen(s))) ;
515                 strcpy(buf[i].f_mntfromname,host) ;
516                 strcat(buf[i].f_mntfromname,":") ;
517                 strcat(buf[i].f_mntfromname,path) ;
518             }
519             entry = &buf[i];
520
521 #elif defined(OPT_SVR4_GETMNTENT)
522         int rc;     
523         while (! (rc = getmntent(mount_table, &entry)))
524 #else               
525         while (entry = getmntent(mount_table))
526 #endif
527 #if !defined(CSRG_BASED)
528         {
529 #endif
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":"");
539 #endif                  
540                         _tt_global->fileSystemEntries->append(fse);
541                 }
542         }
543
544         ttCloseMntTbl(mount_table);
545 }
546
547 void _Tt_file_system::
548 flush ()
549 {
550         if (!_tt_global->fileSystemEntries.is_null()) {
551                 _tt_global->fileSystemEntries->flush();
552         }
553
554         lastMountTime = 0;
555 }
556 /* Local Variables : */
557 /* c++-indent-level: 2 */
558 /* End: */