and added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / host / hr_partition.c
1
2 /*
3  *  Host Resources MIB - partition device group implementation - hr_partition.c
4  *
5  */
6
7 #include <net-snmp/net-snmp-config.h>
8 #include <fcntl.h>
9 #if HAVE_STRING_H
10 #include <string.h>
11 #else
12 #include <strings.h>
13 #endif
14 #if HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 #include <errno.h>
18
19 #include "host_res.h"
20 #include "hr_partition.h"
21 #include "hr_filesys.h"
22 #include "hr_disk.h"
23
24 #include <sys/stat.h>
25
26 #define HRP_MONOTONICALLY_INCREASING
27
28         /*********************
29          *
30          *  Kernel & interface information,
31          *   and internal forward declarations
32          *
33          *********************/
34
35 static int      HRP_savedDiskIndex;
36 static int      HRP_savedPartIndex;
37 static char     HRP_savedName[100];
38
39 static int      HRP_DiskIndex;
40
41 static void     Save_HR_Partition(int, int);
42
43
44         /*********************
45          *
46          *  Initialisation & common implementation functions
47          *
48          *********************/
49
50 static void     Init_HR_Partition(void);
51 static int      Get_Next_HR_Partition(void);
52 int             header_hrpartition(struct variable *, oid *, size_t *, int,
53                                    size_t *, WriteMethod **);
54
55
56 #define HRPART_INDEX            1
57 #define HRPART_LABEL            2
58 #define HRPART_ID               3
59 #define HRPART_SIZE             4
60 #define HRPART_FSIDX            5
61
62 struct variable4 hrpartition_variables[] = {
63     {HRPART_INDEX, ASN_INTEGER, RONLY, var_hrpartition, 2, {1, 1}},
64     {HRPART_LABEL, ASN_OCTET_STR, RONLY, var_hrpartition, 2, {1, 2}},
65     {HRPART_ID, ASN_OCTET_STR, RONLY, var_hrpartition, 2, {1, 3}},
66     {HRPART_SIZE, ASN_INTEGER, RONLY, var_hrpartition, 2, {1, 4}},
67     {HRPART_FSIDX, ASN_INTEGER, RONLY, var_hrpartition, 2, {1, 5}}
68 };
69 oid             hrpartition_variables_oid[] =
70     { 1, 3, 6, 1, 2, 1, 25, 3, 7 };
71
72
73 void
74 init_hr_partition(void)
75 {
76     REGISTER_MIB("host/hr_partition", hrpartition_variables, variable4,
77                  hrpartition_variables_oid);
78 }
79
80
81 /*
82  * header_hrpartition(...
83  * Arguments:
84  * vp     IN      - pointer to variable entry that points here
85  * name    IN/OUT  - IN/name requested, OUT/name found
86  * length  IN/OUT  - length of IN/OUT oid's 
87  * exact   IN      - TRUE if an exact match was requested
88  * var_len OUT     - length of variable or 0 if function returned
89  * write_method
90  * 
91  */
92
93 int
94 header_hrpartition(struct variable *vp,
95                    oid * name,
96                    size_t * length,
97                    int exact,
98                    size_t * var_len, WriteMethod ** write_method)
99 {
100 #define HRPART_DISK_NAME_LENGTH         11
101 #define HRPART_ENTRY_NAME_LENGTH        12
102     oid             newname[MAX_OID_LEN];
103     int             part_idx, LowDiskIndex = -1, LowPartIndex = -1;
104     int             result;
105
106     DEBUGMSGTL(("host/hr_partition", "var_hrpartition: "));
107     DEBUGMSGOID(("host/hr_partition", name, *length));
108     DEBUGMSG(("host/hr_partition", " %d\n", exact));
109
110     memcpy((char *) newname, (char *) vp->name,
111            (int) vp->namelen * sizeof(oid));
112     /*
113      * Find "next" partition entry 
114      */
115
116     Init_HR_Disk();
117     Init_HR_Partition();
118
119     /*
120      *  Find the "next" disk and partition entries.
121      *  If we're in the middle of the table, then there's
122      *     no point in examining earlier disks, so set the
123      *     starting disk to that of the variable being queried.
124      *
125      *  If we've moved from one column of the table to another,
126      *     then we need to start at the beginning again.
127      *     (i.e. the 'compare' fails to match)
128      *  Similarly if we're at the start of the table
129      *     (i.e. *length is too short to be a full instance)
130      */
131
132     if ((snmp_oid_compare(vp->name, vp->namelen, name, vp->namelen) == 0)
133         && (*length > HRPART_DISK_NAME_LENGTH)) {
134         LowDiskIndex =
135             (name[HRPART_DISK_NAME_LENGTH] &
136              ((1 << HRDEV_TYPE_SHIFT) - 1));
137
138         while (HRP_DiskIndex < LowDiskIndex) {
139             Init_HR_Partition();        /* moves to next disk */
140             if (HRP_DiskIndex == -1)
141                 return (MATCH_FAILED);
142         }
143     }
144
145     for (;;) {
146         part_idx = Get_Next_HR_Partition();
147         if (part_idx == 0)
148             break;
149         newname[HRPART_DISK_NAME_LENGTH] =
150             (HRDEV_DISK << HRDEV_TYPE_SHIFT) + HRP_DiskIndex;
151         newname[HRPART_ENTRY_NAME_LENGTH] = part_idx;
152         result = snmp_oid_compare(name, *length, newname, vp->namelen + 2);
153         if (exact && (result == 0)) {
154             Save_HR_Partition(HRP_DiskIndex, part_idx);
155             LowDiskIndex = HRP_DiskIndex;
156             LowPartIndex = part_idx;
157             break;
158         }
159         if (!exact && (result < 0)) {
160             if (LowPartIndex == -1) {
161                 Save_HR_Partition(HRP_DiskIndex, part_idx);
162                 LowDiskIndex = HRP_DiskIndex;
163                 LowPartIndex = part_idx;
164             } else if (LowDiskIndex < HRP_DiskIndex)
165                 break;
166             else if (part_idx < LowPartIndex) {
167                 Save_HR_Partition(HRP_DiskIndex, part_idx);
168                 LowDiskIndex = HRP_DiskIndex;
169                 LowPartIndex = part_idx;
170             }
171 #ifdef HRP_MONOTONICALLY_INCREASING
172             break;
173 #endif
174         }
175     }
176
177     if (LowPartIndex == -1) {
178         DEBUGMSGTL(("host/hr_partition", "... index out of range\n"));
179         return (MATCH_FAILED);
180     }
181
182     newname[HRPART_DISK_NAME_LENGTH] =
183         (HRDEV_DISK << HRDEV_TYPE_SHIFT) + LowDiskIndex;
184     newname[HRPART_ENTRY_NAME_LENGTH] = LowPartIndex;
185     memcpy((char *) name, (char *) newname,
186            ((int) vp->namelen + 2) * sizeof(oid));
187     *length = vp->namelen + 2;
188     *write_method = 0;
189     *var_len = sizeof(long);    /* default to 'long' results */
190
191     DEBUGMSGTL(("host/hr_partition", "... get partition stats "));
192     DEBUGMSGOID(("host/hr_partition", name, *length));
193     DEBUGMSG(("host/hr_partition", "\n"));
194     return LowPartIndex;
195 }
196
197
198         /*********************
199          *
200          *  System specific implementation functions
201          *
202          *********************/
203
204
205 u_char         *
206 var_hrpartition(struct variable * vp,
207                 oid * name,
208                 size_t * length,
209                 int exact, size_t * var_len, WriteMethod ** write_method)
210 {
211     int             part_idx;
212     static char     string[100];
213     struct stat     stat_buf;
214
215     part_idx =
216         header_hrpartition(vp, name, length, exact, var_len, write_method);
217     if (part_idx == MATCH_FAILED)
218         return NULL;
219
220     if (stat(HRP_savedName, &stat_buf) == -1)
221         return NULL;
222
223     switch (vp->magic) {
224     case HRPART_INDEX:
225         long_return = part_idx;
226         return (u_char *) & long_return;
227     case HRPART_LABEL:
228         *var_len = strlen(HRP_savedName);
229         return (u_char *) HRP_savedName;
230     case HRPART_ID:            /* Use the device number */
231         sprintf(string, "0x%x", (int) stat_buf.st_rdev);
232         *var_len = strlen(string);
233         return (u_char *) string;
234     case HRPART_SIZE:
235         /*
236          * XXX - based on single partition assumption 
237          */
238         long_return = Get_FSSize(HRP_savedName);
239         return (u_char *) & long_return;
240     case HRPART_FSIDX:
241         long_return = Get_FSIndex(HRP_savedName);
242         return (u_char *) & long_return;
243     default:
244         DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrpartition\n",
245                     vp->magic));
246     }
247     return NULL;
248 }
249
250
251         /*********************
252          *
253          *  Internal implementation functions
254          *
255          *********************/
256
257 static int      HRP_index;
258
259 static void
260 Init_HR_Partition(void)
261 {
262     HRP_DiskIndex = Get_Next_HR_Disk();
263     if (HRP_DiskIndex != -1)
264         HRP_DiskIndex &= ((1 << HRDEV_TYPE_SHIFT) - 1);
265
266     HRP_index = -1;
267 }
268
269 static int
270 Get_Next_HR_Partition(void)
271 {
272     char            string[100];
273     int             fd;
274
275     if (HRP_DiskIndex == -1) {
276         return 0;
277     }
278
279     HRP_index++;
280     while (Get_Next_HR_Disk_Partition(string, HRP_index) != -1) {
281         DEBUGMSGTL(("host/hr_partition",
282                     "Get_Next_HR_Partition: %s (:%d)\n",
283                     string, HRP_index));
284
285         fd = open(string, O_RDONLY);
286         if (fd != -1) {
287             close(fd);
288             return HRP_index + 1;
289         } else if (errno == EBUSY) {
290             return HRP_index + 1;
291         }
292         HRP_index++;
293     }
294
295     /*
296      * Finished with this disk, try the next
297      */
298     Init_HR_Partition();
299     return (Get_Next_HR_Partition());
300 }
301
302 static void
303 Save_HR_Partition(int disk_idx, int part_idx)
304 {
305     HRP_savedDiskIndex = disk_idx;
306     HRP_savedPartIndex = part_idx;
307     (void) Get_Next_HR_Disk_Partition(HRP_savedName, HRP_index);
308 }