Define LSOF_CC to system CC
[platform/upstream/lsof.git] / lib / rmnt.c
1 /*
2  * rmnt.c -- readmnt() function for lsof library
3  */
4
5
6 /*
7  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
8  * 47907.  All rights reserved.
9  *
10  * Written by Victor A. Abell
11  *
12  * This software is not subject to any license of the American Telephone
13  * and Telegraph Company or the Regents of the University of California.
14  *
15  * Permission is granted to anyone to use this software for any purpose on
16  * any computer system, and to alter it and redistribute it freely, subject
17  * to the following restrictions:
18  *
19  * 1. Neither the authors nor Purdue University are responsible for any
20  *    consequences of the use of this software.
21  *
22  * 2. The origin of this software must not be misrepresented, either by
23  *    explicit claim or by omission.  Credit to the authors and Purdue
24  *    University must appear in documentation and sources.
25  *
26  * 3. Altered versions must be plainly marked as such, and must not be
27  *    misrepresented as being the original software.
28  *
29  * 4. This notice may not be removed or altered.
30  */
31
32
33 #include "../machine.h"
34
35 #if     defined(USE_LIB_READMNT)
36
37 # if    !defined(lint)
38 static char copyright[] =
39 "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
40 static char *rcsid = "$Id: rmnt.c,v 1.12 2008/10/21 16:13:23 abe Exp $";
41 # endif /* !defined(lint) */
42
43 #include "../lsof.h"
44
45
46
47 /*
48  * The caller may define:
49  *
50  * 1.  An RMNT_EXPDEV macro to expand (ala EP/IX) device numbers;
51  *
52  *     EP/IX, for example, uses:
53  *
54  *      #define RMNT_EXPDEV(n) expdev(n)
55  *
56  * 2.  A custom macro, MNTSKIP, for making decisions to skip entries
57  *     -- e.g., ones whose mnt_type is MNTTYPE_IGNORE.
58  *
59  * 3.  RMNT_FSTYPE to specify the member name of the character string of the
60  *     mntent structure containing the file system type, and MOUNTS_FSTYPE to
61  *     specify the member name of the character string pointer of the local
62  *     mounts structure where RMNT_FSTYPE is to be copied.
63  *
64  * 4.  RMNT_STAT_FSTYPE to specify the member name of the stat structure
65  *     containing an integer file system type, and MOUNTS_STAT_FSTYPE to
66  *     specify the member name of the integer in the local mounts structure
67  *     where RMNT_STAT_FSTYPE is to be copied.
68  *     
69  */
70
71 #if     !defined(RMNT_EXPDEV)
72 #define RMNT_EXPDEV(n)  n
73 #endif  /* !defined(RMNT_EXPDEV) */
74
75
76 /*
77  * Local static definitions
78  */
79
80 static struct mounts *Lmi = (struct mounts *)NULL;      /* local mount info */
81 static int Lmist = 0;                                   /* Lmi status */
82
83
84 /*
85  * readmnt() - read mount table
86  */
87
88 struct mounts *
89 readmnt()
90 {
91         char *dn = (char *)NULL;
92         char *ln;
93         FILE *mfp;
94         struct mntent *mp;
95         struct mounts *mtp;
96         char *opt, *opte;
97         struct stat sb;
98
99         if (Lmi || Lmist)
100             return(Lmi);
101 /*
102  * Open access to the mount table.
103  */
104         if (!(mfp = setmntent(MOUNTED, "r"))) {
105             (void) fprintf(stderr, "%s: can't access %s\n", Pn, MOUNTED);
106             Exit(1);
107         }
108 /*
109  * Read mount table entries.
110  */
111         while ((mp = getmntent(mfp))) {
112
113 #if     defined(MNTSKIP)
114         /*
115          * Specfy in the MNTSKIP macro the decisions needed to determine
116          * that this entry should be skipped.
117          *
118          * Typically entries whose mnt_type is MNTTYPE_IGNORE are skipped.
119          *
120          * The MNTSKIP macro allows the caller to use other tests.
121          */
122             MNTSKIP
123 #endif  /* MNTSKIP */
124
125         /*
126          * Interpolate a possible symbolic directory link.
127          */
128             if (dn)
129                 (void) free((FREE_P *)dn);
130             if (!(dn = mkstrcpy(mp->mnt_dir, (MALLOC_S *)NULL)))
131                 goto no_space_for_mount;
132             if (!(ln = Readlink(dn))) {
133                 if (!Fwarn)
134                     (void) fprintf(stderr,
135                         "      Output information may be incomplete.\n");
136                 continue;
137             }
138             if (ln != dn) {
139                 (void) free((FREE_P *)dn);
140                 dn = ln;
141             }
142             if (*dn != '/')
143                 continue;
144         /*
145          * Stat() the directory.
146          */
147             if (statsafely(dn, &sb)) {
148                 if (!Fwarn) {
149                     (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
150                     safestrprt(mp->mnt_type, stderr, 0);
151                     (void) fprintf(stderr, " file system ");
152                     safestrprt(mp->mnt_dir, stderr, 1);
153                     (void) fprintf(stderr,
154                         "      Output information may be incomplete.\n");
155                 }
156                 if ((opt = strstr(mp->mnt_opts, "dev="))) {
157                     (void) zeromem(&sb, sizeof(sb));
158                     if ((opte = x2dev(opt + 4, (dev_t *)&sb.st_dev))) {
159                         sb.st_mode = S_IFDIR | 0777;
160                         if (!Fwarn)
161                             (void) fprintf(stderr,
162                                 "      assuming \"%.*s\" from %s\n",
163                                 (int)(opte - opt), opt, MOUNTED);
164                     } else
165                         opt = (char *)NULL;
166                 }
167                 if (!opt)
168                     continue;
169             }
170         /*
171          * Allocate and fill a local mounts structure with the directory
172          * (mounted) information.
173          */
174             if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) {
175
176 no_space_for_mount:
177
178                 (void) fprintf(stderr, "%s: no space for mount at ", Pn);
179                 safestrprt(mp->mnt_fsname, stderr, 0);
180                 (void) fprintf(stderr, " (");
181                 safestrprt(mp->mnt_dir, stderr, 0);
182                 (void) fprintf(stderr, ")\n");
183                 Exit(1);
184             }
185             mtp->dir = dn;
186             dn = (char *)NULL;
187             mtp->next = Lmi;
188             mtp->dev = RMNT_EXPDEV(sb.st_dev);
189             mtp->rdev = RMNT_EXPDEV(sb.st_rdev);
190             mtp->inode = (INODETYPE)sb.st_ino;
191             mtp->mode = sb.st_mode;
192
193 # if    defined(RMNT_FSTYPE) && defined(MOUNTS_FSTYPE)
194         /*
195          * Make a copy of RMNT_FSTYPE in MOUNTS_FSTYPE.
196          */
197             if (!(mtp->MOUNTS_FSTYPE = mkstrcpy(mp->RMNT_FSTYPE,
198                                                 (MALLOC_S *)NULL)))
199             {
200                 (void) fprintf(stderr, "%s: no space for fstype (%s): %s\n",
201                     Pn, mtp->dir, mp->RMNT_FSTYPE);
202                 Exit(1);
203             }
204             (void) strcpy(mtp->MOUNTS_FSTYPE, mp->RMNT_FSTYPE);
205 # endif /* defined(RMNT_FSTYP) && defined(MOUNTS_FSTYP) */
206
207 # if    defined(RMNT_STAT_FSTYPE) && defined(MOUNTS_STAT_FSTYPE)
208         /*
209          * Make a copy of RMNT_STAT_FSTYPE in MOUNTS_STAT_FSTYPE.
210          */
211             mtp->MOUNTS_STAT_FSTYPE = (int)sb.RMNT_STAT_FSTYPE;
212 # endif /* defined(RMNT_STAT_FSTYP) && defined(MOUNTS_STAT_FSTYP) */
213
214         /*
215          * Interpolate a possible file system (mounted-on device) name link.
216          */
217             if (!(dn = mkstrcpy(mp->mnt_fsname, (MALLOC_S *)NULL)))
218                 goto no_space_for_mount;
219             mtp->fsname = dn;
220             ln = Readlink(dn);
221             dn = (char *)NULL;
222         /*
223          * Stat() the file system (mounted-on) name and add file system
224          * information to the local mounts structure.
225          */
226             if (!ln || statsafely(ln, &sb))
227                 sb.st_mode = 0;
228             mtp->fsnmres = ln;
229             mtp->fs_mode = sb.st_mode;
230             Lmi = mtp;
231         }
232         (void) endmntent(mfp);
233 /*
234  * Clean up and return the local nount info table address.
235  */
236         if (dn)
237             (void) free((FREE_P *)dn);
238         Lmist = 1;
239         return(Lmi);
240 }
241 #else   /* !defined(USE_LIB_READMNT) */
242 char rmnt_d1[] = "d"; char *rmnt_d2 = rmnt_d1;
243 #endif  /* defined(USE_LIB_READMNT) */