Imported Upstream version 4.87
[platform/upstream/lsof.git] / lib / isfn.c
1 /*
2  * isfn.c -- is_file_named() 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 /*
34  * To use this source file:
35  *
36  * 1. Define USE_LIB_IS_FILE_NAMED.
37  *
38  * 2. If clone support is required:
39  *
40  *    a.  Define HAVECLONEMAJ to be the name of the variable that
41  *        contains the status of the clone major device -- e.g.,
42  *
43  *              #define HAVECLONEMAJ HaveCloneMaj
44  *
45  *    b.  Define CLONEMAJ to be the name of the constant or
46  *        variable that defines the clone major device -- e.g.,
47  *
48  *              #define CLONEMAJ CloneMaj
49  *
50  *    c.  Make sure that clone devices are identified by an lfile
51  *        element is_stream value of 1.
52  *
53  *    d.  Accept clone searching by device number only.
54  */
55
56
57 #include "../machine.h"
58
59 #if     defined(USE_LIB_IS_FILE_NAMED)
60
61 # if    !defined(lint)
62 static char copyright[] =
63 "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
64 static char *rcsid = "$Id: isfn.c,v 1.10 2008/10/21 16:12:36 abe Exp $";
65 # endif /* !defined(lint) */
66
67 #include "../lsof.h"
68
69
70 /*
71  * Local structures
72  */
73
74 struct hsfile {
75         struct sfile *s;                /* the Sfile table address */
76         struct hsfile *next;            /* the next hash bucket entry */
77 };
78
79 /*
80  * Local static variables
81  */
82
83 # if    defined(HAVECLONEMAJ)
84 static struct hsfile *HbyCd =           /* hash by clone buckets */
85         (struct hsfile *)NULL;
86 static int HbyCdCt = 0;                 /* HbyCd entry count */
87 # endif /* defined(HAVECLONEMAJ) */
88
89 static struct hsfile *HbyFdi =          /* hash by file (dev,ino) buckets */
90         (struct hsfile *)NULL;
91 static int HbyFdiCt = 0;                /* HbyFdi entry count */
92 static struct hsfile *HbyFrd =          /* hash by file raw device buckets */
93         (struct hsfile *)NULL;
94 static int HbyFrdCt = 0;                /* HbyFrd entry count */
95 static struct hsfile *HbyFsd =          /* hash by file system buckets */
96         (struct hsfile *)NULL;
97 static int HbyFsdCt = 0;                /* HbyFsd entry count */
98 static struct hsfile *HbyNm =           /* hash by name buckets */
99         (struct hsfile *)NULL;
100 static int HbyNmCt = 0;                 /* HbyNm entry count */
101
102
103 /*
104  * Local definitions
105  */
106
107 # if    defined(HAVECLONEMAJ)
108 #define SFCDHASH        1024            /* Sfile hash by clone device (power
109                                          * of 2!) */
110 # endif /* defined(HAVECLONEMAJ) */
111
112 #define SFDIHASH        4094            /* Sfile hash by (device,inode) number
113                                          * pair bucket count (power of 2!) */
114 #define SFFSHASH        1024            /* Sfile hash by file system device
115                                          * number bucket count (power of 2!) */
116 #define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1)))
117                                         /* hash for Sfile by major device,
118                                          * minor device, and inode, modulo mod
119                                          * (mod must be a power of 2) */
120 #define SFRDHASH        1024            /* Sfile hash by raw device number
121                                          * bucket count (power of 2!) */
122 #define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1)))
123                                         /* hash for Sfile by major device,
124                                          * minor device, major raw device,
125                                          * minor raw device, and inode, modulo
126                                          * mod (mod must be a power of 2) */
127 #define SFNMHASH        4096            /* Sfile hash by name bucket count
128                                          * (must be a power of 2!) */
129
130
131
132 /*
133  * hashSfile() - hash Sfile entries for use in is_file_named() searches
134  */
135
136 void
137 hashSfile()
138 {
139         static int hs = 0;
140         int i;
141         int sfplm = 3;
142         struct sfile *s;
143         struct hsfile *sh, *sn;
144 /*
145  * Do nothing if there are no file search arguments cached or if the
146  * hashes have already been constructed.
147  */
148         if (!Sfile || hs)
149             return;
150 /*
151  * Allocate hash buckets by (device,inode), file system device, and file name.
152  */
153
154 # if    defined(HAVECLONEMAJ)
155         if (HAVECLONEMAJ) {
156             if (!(HbyCd = (struct hsfile *)calloc((MALLOC_S)SFCDHASH,
157                                                   sizeof(struct hsfile))))
158             {
159                 (void) fprintf(stderr,
160                     "%s: can't allocate space for %d clone hash buckets\n",
161                     Pn, SFCDHASH);
162                 Exit(1);
163             }
164             sfplm++;
165         }
166 # endif /* defined(HAVECLONEMAJ) */
167
168         if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH,
169                                                sizeof(struct hsfile))))
170         {
171             (void) fprintf(stderr,
172                 "%s: can't allocate space for %d (dev,ino) hash buckets\n",
173                 Pn, SFDIHASH);
174             Exit(1);
175         }
176         if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH,
177                                                sizeof(struct hsfile))))
178         {
179             (void) fprintf(stderr,
180                 "%s: can't allocate space for %d rdev hash buckets\n",
181                 Pn, SFRDHASH);
182             Exit(1);
183         }
184         if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH,
185                                                sizeof(struct hsfile))))
186         {
187             (void) fprintf(stderr,
188                 "%s: can't allocate space for %d file sys hash buckets\n",
189                 Pn, SFFSHASH);
190             Exit(1);
191         }
192         if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH,
193                                               sizeof(struct hsfile))))
194         {
195             (void) fprintf(stderr,
196                 "%s: can't allocate space for %d name hash buckets\n",
197                 Pn, SFNMHASH);
198             Exit(1);
199         }
200         hs++;
201 /*
202  * Scan the Sfile chain, building file, file system, raw device, and file
203  * name hash bucket chains.
204  */
205         for (s = Sfile; s; s = s->next) {
206             for (i = 0; i < sfplm; i++) {
207                 if (i == 0) {
208                     if (!s->aname)
209                         continue;
210                     sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
211                     HbyNmCt++;
212                 } else if (i == 1) {
213                     if (s->type) {
214                         sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
215                                                   GET_MIN_DEV(s->dev), s->i,
216                                                   SFDIHASH)];
217                         HbyFdiCt++;
218                     } else {
219                         sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
220                                                   GET_MIN_DEV(s->dev),
221                                                   0,
222                                                   SFFSHASH)];
223                         HbyFsdCt++;
224                     }
225                 } else if (i == 2) {
226                     if ((s->mode == S_IFCHR) || (s->mode == S_IFBLK)) {
227                         sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev),
228                                                  GET_MIN_DEV(s->dev),
229                                                  GET_MAJ_DEV(s->rdev),
230                                                  GET_MIN_DEV(s->rdev),
231                                                  s->i,
232                                                  SFRDHASH)];
233                         HbyFrdCt++;
234                     } else
235                         continue;
236                 }
237
238 # if    defined(HAVECLONEMAJ)
239                 else {
240                     if (!HAVECLONEMAJ || (GET_MAJ_DEV(s->rdev) != CLONEMAJ))
241                         continue;
242                     sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0,
243                                              SFCDHASH)];
244                     HbyCdCt++;
245                 }
246 # else  /* ! defined(HAVECLONEMAJ) */
247                 else
248                     continue;
249 # endif /* defined(HAVECLONEMAJ) */
250
251                 if (!sh->s) {
252                     sh->s = s;
253                     sh->next = (struct hsfile *)NULL;
254                     continue;
255                 } else {
256                     if (!(sn = (struct hsfile *)malloc(
257                                 (MALLOC_S)sizeof(struct hsfile))))
258                     {
259                         (void) fprintf(stderr,
260                             "%s: can't allocate hsfile bucket for: %s\n",
261                             Pn, s->aname);
262                         Exit(1);
263                     }
264                     sn->s = s;
265                     sn->next = sh->next;
266                     sh->next = sn;
267                 }
268             }
269         }
270 }
271
272
273 /*
274  * is_file_named() - is this file named?
275  */
276
277 int
278 is_file_named(p, cd)
279         char *p;                        /* path name; NULL = search by device
280                                          * and inode (from *Lf) */
281         int cd;                         /* character or block type file --
282                                          * VCHR or VBLK vnode, or S_IFCHR
283                                          * or S_IFBLK inode */
284 {
285         char *ep;
286         int f = 0;
287         struct sfile *s = (struct sfile *)NULL;
288         struct hsfile *sh;
289         size_t sz;
290 /*
291  * Check for a path name match, as requested.
292  */
293         if (p && HbyNmCt) {
294             for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) {
295                 if ((s = sh->s) && strcmp(p, s->aname) == 0) {
296                     f = 2;
297                     break;
298                 }
299             }
300         }
301
302 # if    defined(HAVECLONEMAJ)
303 /*
304  * If this is a stream, check for a clone device match.
305  */
306         if (!f && HbyCdCt && Lf->is_stream && Lf->dev_def && Lf->rdev_def
307         &&  (Lf->dev == DevDev))
308         {
309             for (sh = &HbyCd[SFHASHDEVINO(0, GET_MAJ_DEV(Lf->rdev), 0,
310                                           SFCDHASH)];
311                  sh;
312                  sh = sh->next)
313             {
314                 if ((s = sh->s) && (GET_MAJ_DEV(Lf->rdev)
315                 ==                  GET_MIN_DEV(s->rdev))) {
316                     f = 3;
317                     break;
318                 }
319             }
320         }
321 # endif /* defined(HAVECLONEMAJ) */
322
323 /*
324  * Check for a regular file.
325  */
326         if (!f && HbyFdiCt && Lf->dev_def
327         && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
328         {
329             for (sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
330                                            GET_MIN_DEV(Lf->dev),
331                                            Lf->inode,
332                                            SFDIHASH)];
333                  sh;
334                  sh = sh->next)
335             {
336                 if ((s = sh->s) && (Lf->dev == s->dev)
337                 &&  (Lf->inode == s->i)) {
338                     f = 1;
339                     break;
340                 }
341             }
342         }
343 /*
344  * Check for a file system match.
345  */
346         if (!f && HbyFsdCt && Lf->dev_def) {
347             for (sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
348                                            GET_MIN_DEV(Lf->dev), 0,
349                                            SFFSHASH)];
350                  sh;
351                  sh = sh->next)
352             {
353                 if ((s = sh->s) && (s->dev == Lf->dev)) {
354                     f = 1;
355                     break;
356                 }
357             }
358         }
359 /*
360  * Check for a character or block device match.
361  */
362         if (!f && HbyFrdCt && cd
363         &&  Lf->dev_def && (Lf->dev == DevDev)
364         &&  Lf->rdev_def
365         && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
366         {
367             for (sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(Lf->dev),
368                                           GET_MIN_DEV(Lf->dev),
369                                           GET_MAJ_DEV(Lf->rdev),
370                                           GET_MIN_DEV(Lf->rdev),
371                                           Lf->inode, SFRDHASH)];
372                  sh;
373                  sh = sh->next)
374             {
375                 if ((s = sh->s) && (s->dev == Lf->dev)
376                 &&  (s->rdev == Lf->rdev) && (s->i == Lf->inode))
377                 {
378                     f = 1;
379                     break;
380                 }
381             }
382         }
383 /*
384  * Convert the name if a match occurred.
385  */
386         switch (f) {
387         case 0:
388             return(0);
389         case 1:
390             if (s->type) {
391
392             /*
393              * If the search argument isn't a file system, propagate it
394              * to Namech[]; otherwise, let printname() compose the name.
395              */
396                 (void) snpf(Namech, Namechl, "%s", s->name);
397                 if (s->devnm) {
398                     ep = endnm(&sz);
399                     (void) snpf(ep, sz, " (%s)", s->devnm);
400                 }
401             }
402             break;
403         case 2:
404             (void) strcpy(Namech, p);
405             break;
406
407 # if    defined(HAVECLONEMAJ)
408         /* case 3:              do nothing for stream clone matches */
409 # endif /* defined(HAVECLONEMAJ) */
410
411         }
412         if (s)
413             s->f = 1;
414         return(1);
415 }
416 #else   /* !defined(USE_LIB_IS_FILE_NAMED) */
417 char isfn_d1[] = "d"; char *isfn_d2 = isfn_d1;
418 #endif  /* defined(USE_LIB_IS_FILE_NAMED) */