1154133Sharti/*-
2154133Sharti * Copyright (c) 2005-2006 The FreeBSD Project
3154133Sharti * All rights reserved.
4154133Sharti *
5154133Sharti * Author: Victor Cruceru <soc-victor@freebsd.org>
6154133Sharti *
7154133Sharti * Redistribution of this software and documentation and use in source and
8154133Sharti * binary forms, with or without modification, are permitted provided that
9154133Sharti * the following conditions are met:
10154133Sharti *
11154133Sharti * 1. Redistributions of source code or documentation must retain the above
12154133Sharti *    copyright notice, this list of conditions and the following disclaimer.
13154133Sharti * 2. Redistributions in binary form must reproduce the above copyright
14154133Sharti *    notice, this list of conditions and the following disclaimer in the
15154133Sharti *    documentation and/or other materials provided with the distribution.
16154133Sharti *
17154133Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18154133Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19154133Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20154133Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21154133Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22154133Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23154133Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24154133Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25154133Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26154133Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27154133Sharti * SUCH DAMAGE.
28154133Sharti *
29154133Sharti * $FreeBSD: stable/10/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c 344747 2019-03-04 03:38:43Z avos $
30154133Sharti */
31154133Sharti
32154133Sharti/*
33154133Sharti * Host Resources MIB: hrPartitionTable implementation for SNMPd.
34154133Sharti */
35154133Sharti
36154133Sharti#include <sys/types.h>
37154133Sharti#include <sys/limits.h>
38154133Sharti
39154133Sharti#include <assert.h>
40154133Sharti#include <err.h>
41154856Sharti#include <inttypes.h>
42154856Sharti#include <libgeom.h>
43154133Sharti#include <paths.h>
44154133Sharti#include <stdlib.h>
45154133Sharti#include <string.h>
46154133Sharti#include <syslog.h>
47160341Sharti#include <sysexits.h>
48154133Sharti
49154133Sharti#include "hostres_snmp.h"
50154133Sharti#include "hostres_oid.h"
51154133Sharti#include "hostres_tree.h"
52154133Sharti
53154856Sharti#ifdef PC98
54160341Sharti#define	HR_FREEBSD_PART_TYPE	0xc494
55154856Sharti#else
56154856Sharti#define	HR_FREEBSD_PART_TYPE	165
57154856Sharti#endif
58154856Sharti
59160341Sharti/* Maximum length for label and id including \0 */
60160341Sharti#define	PART_STR_MLEN	(128 + 1)
61160341Sharti
62154133Sharti/*
63154133Sharti * One row in the hrPartitionTable
64154133Sharti */
65154133Shartistruct partition_entry {
66160341Sharti	asn_subid_t	index[2];
67160341Sharti	u_char		*label;	/* max allocated len will be PART_STR_MLEN */
68160341Sharti	u_char		*id;	/* max allocated len will be PART_STR_MLEN */
69154133Sharti	int32_t		size;
70154133Sharti	int32_t		fs_Index;
71154133Sharti	TAILQ_ENTRY(partition_entry) link;
72160341Sharti#define	HR_PARTITION_FOUND		0x001
73154133Sharti	uint32_t	flags;
74154133Sharti};
75154133ShartiTAILQ_HEAD(partition_tbl, partition_entry);
76154133Sharti
77154133Sharti/*
78154133Sharti * This table is used to get a consistent indexing. It saves the name -> index
79154133Sharti * mapping while we rebuild the partition table.
80154133Sharti */
81154133Shartistruct partition_map_entry {
82160341Sharti	int32_t		index;	/* partition_entry::index */
83160341Sharti	u_char		*id;	/* max allocated len will be PART_STR_MLEN */
84154133Sharti
85154133Sharti	/*
86154133Sharti	 * next may be NULL if the respective partition_entry
87154133Sharti	 * is (temporally) gone.
88154133Sharti	 */
89154133Sharti	struct partition_entry	*entry;
90154133Sharti	STAILQ_ENTRY(partition_map_entry) link;
91154133Sharti};
92154133ShartiSTAILQ_HEAD(partition_map, partition_map_entry);
93154133Sharti
94154133Sharti/* Mapping table for consistent indexing */
95154133Shartistatic struct partition_map partition_map =
96154133Sharti    STAILQ_HEAD_INITIALIZER(partition_map);
97154133Sharti
98154133Sharti/* THE partition table. */
99154133Shartistatic struct partition_tbl partition_tbl =
100154133Sharti    TAILQ_HEAD_INITIALIZER(partition_tbl);
101154133Sharti
102154133Sharti/* next int available for indexing the hrPartitionTable */
103154133Shartistatic uint32_t next_partition_index = 1;
104154133Sharti
105160341Sharti/*
106160341Sharti * Partition_entry_cmp is used for INSERT_OBJECT_FUNC_LINK
107160341Sharti * macro.
108160341Sharti */
109160341Shartistatic int
110160341Shartipartition_entry_cmp(const struct partition_entry *a,
111160341Sharti    const struct partition_entry *b)
112160341Sharti{
113160341Sharti	assert(a != NULL);
114160341Sharti	assert(b != NULL);
115160341Sharti
116160341Sharti	if (a->index[0] < b->index[0])
117160341Sharti		return (-1);
118160341Sharti
119160341Sharti	if (a->index[0] > b->index[0])
120160341Sharti		return (+1);
121160341Sharti
122160341Sharti	if (a->index[1] < b->index[1])
123160341Sharti		return (-1);
124160341Sharti
125160341Sharti	if (a->index[1] > b->index[1])
126160341Sharti		return (+1);
127160341Sharti
128160341Sharti	return (0);
129160341Sharti}
130160341Sharti
131160341Sharti/*
132160341Sharti * Partition_idx_cmp is used for NEXT_OBJECT_FUNC and FIND_OBJECT_FUNC
133160341Sharti * macros
134160341Sharti */
135160341Shartistatic int
136160341Shartipartition_idx_cmp(const struct asn_oid *oid, u_int sub,
137160341Sharti    const struct partition_entry *entry)
138160341Sharti{
139160341Sharti	u_int i;
140160341Sharti
141160341Sharti	for (i = 0; i < 2 && i < oid->len - sub; i++) {
142160341Sharti		if (oid->subs[sub + i] < entry->index[i])
143160341Sharti			return (-1);
144160341Sharti		if (oid->subs[sub + i] > entry->index[i])
145160341Sharti			return (+1);
146160341Sharti	}
147160341Sharti	if (oid->len - sub < 2)
148160341Sharti		return (-1);
149160341Sharti	if (oid->len - sub > 2)
150160341Sharti		return (+1);
151160341Sharti
152160341Sharti	return (0);
153160341Sharti}
154160341Sharti
155154133Sharti/**
156154133Sharti * Create a new partition table entry
157154133Sharti */
158154133Shartistatic struct partition_entry *
159154856Shartipartition_entry_create(int32_t ds_index, const char *chunk_name)
160154133Sharti{
161154133Sharti	struct partition_entry *entry;
162160341Sharti	struct partition_map_entry *map;
163160341Sharti	size_t id_len;
164154133Sharti
165154133Sharti	/* sanity checks */
166154856Sharti	assert(chunk_name != NULL);
167154856Sharti	if (chunk_name == NULL || chunk_name[0] == '\0')
168154133Sharti		return (NULL);
169154133Sharti
170154133Sharti	/* check whether we already have seen this partition */
171154133Sharti	STAILQ_FOREACH(map, &partition_map, link)
172160341Sharti		if (strcmp(map->id, chunk_name) == 0)
173154133Sharti			break;
174154133Sharti
175154133Sharti	if (map == NULL) {
176154133Sharti		/* new object - get a new index and create a map */
177160341Sharti
178154133Sharti		if (next_partition_index > INT_MAX) {
179160341Sharti			/* Unrecoverable error - die clean and quicly*/
180310900Sngie			syslog(LOG_ERR, "%s: hrPartitionTable index wrap",
181154133Sharti			    __func__);
182160341Sharti			errx(EX_SOFTWARE, "hrPartitionTable index wrap");
183154133Sharti		}
184154133Sharti
185154133Sharti		if ((map = malloc(sizeof(*map))) == NULL) {
186154133Sharti			syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__);
187154133Sharti			return (NULL);
188154133Sharti		}
189154133Sharti
190160341Sharti		id_len = strlen(chunk_name) + 1;
191160341Sharti		if (id_len > PART_STR_MLEN)
192160341Sharti			id_len = PART_STR_MLEN;
193160341Sharti
194160341Sharti		if ((map->id = malloc(id_len)) == NULL) {
195160341Sharti			free(map);
196160341Sharti			return (NULL);
197160341Sharti		}
198160341Sharti
199154133Sharti		map->index = next_partition_index++;
200154133Sharti
201160341Sharti		strlcpy(map->id, chunk_name, id_len);
202154133Sharti
203160341Sharti		map->entry = NULL;
204160341Sharti
205154133Sharti		STAILQ_INSERT_TAIL(&partition_map, map, link);
206154133Sharti
207154133Sharti		HRDBG("%s added into hrPartitionMap at index=%d",
208154856Sharti		    chunk_name, map->index);
209154133Sharti
210154133Sharti	} else {
211154133Sharti		HRDBG("%s exists in hrPartitionMap index=%d",
212154856Sharti		    chunk_name, map->index);
213154133Sharti	}
214154133Sharti
215160341Sharti	if ((entry = malloc(sizeof(*entry))) == NULL) {
216160341Sharti		syslog(LOG_WARNING, "hrPartitionTable: %s: %m", __func__);
217160341Sharti		return (NULL);
218160341Sharti	}
219160341Sharti	memset(entry, 0, sizeof(*entry));
220160341Sharti
221154133Sharti	/* create the index */
222160341Sharti	entry->index[0] = ds_index;
223160341Sharti	entry->index[1] = map->index;
224154133Sharti
225160341Sharti	map->entry = entry;
226154133Sharti
227160341Sharti	if ((entry->id = strdup(map->id)) == NULL) {
228160341Sharti		free(entry);
229160341Sharti		return (NULL);
230160341Sharti	}
231154133Sharti
232160341Sharti	/*
233160341Sharti	 * reuse id_len from here till the end of this function
234160341Sharti	 * for partition_entry::label
235160341Sharti	 */
236160341Sharti	id_len = strlen(_PATH_DEV) + strlen(chunk_name) + 1;
237154133Sharti
238160341Sharti	if (id_len > PART_STR_MLEN)
239160341Sharti		id_len = PART_STR_MLEN;
240160341Sharti
241160341Sharti	if ((entry->label = malloc(id_len )) == NULL) {
242160341Sharti		free(entry->id);
243160341Sharti		free(entry);
244160341Sharti		return (NULL);
245160341Sharti	}
246160341Sharti
247160341Sharti	snprintf(entry->label, id_len, "%s%s", _PATH_DEV, chunk_name);
248160341Sharti
249160341Sharti	INSERT_OBJECT_FUNC_LINK(entry, &partition_tbl, link,
250160341Sharti	    partition_entry_cmp);
251160341Sharti
252154133Sharti	return (entry);
253154133Sharti}
254154133Sharti
255154133Sharti/**
256154133Sharti * Delete a partition table entry but keep the map entry intact.
257154133Sharti */
258154133Shartistatic void
259154133Shartipartition_entry_delete(struct partition_entry *entry)
260154133Sharti{
261154133Sharti	struct partition_map_entry *map;
262154133Sharti
263154133Sharti	assert(entry != NULL);
264154133Sharti
265154133Sharti	TAILQ_REMOVE(&partition_tbl, entry, link);
266154133Sharti	STAILQ_FOREACH(map, &partition_map, link)
267154133Sharti		if (map->entry == entry) {
268154133Sharti			map->entry = NULL;
269154133Sharti			break;
270154133Sharti		}
271160341Sharti	free(entry->id);
272160341Sharti	free(entry->label);
273154133Sharti	free(entry);
274154133Sharti}
275154133Sharti
276154133Sharti/**
277154133Sharti * Find a partition table entry by name. If none is found, return NULL.
278154133Sharti */
279154133Shartistatic struct partition_entry *
280154133Shartipartition_entry_find_by_name(const char *name)
281154133Sharti{
282154133Sharti	struct partition_entry *entry =  NULL;
283154133Sharti
284154133Sharti	TAILQ_FOREACH(entry, &partition_tbl, link)
285154133Sharti		if (strcmp(entry->id, name) == 0)
286154133Sharti			return (entry);
287154133Sharti
288154133Sharti	return (NULL);
289154133Sharti}
290154133Sharti
291154133Sharti/**
292154133Sharti * Find a partition table entry by label. If none is found, return NULL.
293154133Sharti */
294154133Shartistatic struct partition_entry *
295154133Shartipartition_entry_find_by_label(const char *name)
296154133Sharti{
297154133Sharti	struct partition_entry *entry =  NULL;
298154133Sharti
299154133Sharti	TAILQ_FOREACH(entry, &partition_tbl, link)
300154133Sharti		if (strcmp(entry->label, name) == 0)
301154133Sharti			return (entry);
302154133Sharti
303154133Sharti	return (NULL);
304154133Sharti}
305154133Sharti
306154133Sharti/**
307154856Sharti * Process a chunk from libgeom(4). A chunk is either a slice or a partition.
308154133Sharti * If necessary create a new partition table entry for it. In any case
309154133Sharti * set the size field of the entry and set the FOUND flag.
310154133Sharti */
311154133Shartistatic void
312154856Shartihandle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size)
313154133Sharti{
314160341Sharti	struct partition_entry *entry;
315154133Sharti	daddr_t k_size;
316154133Sharti
317154856Sharti	assert(chunk_name != NULL);
318154856Sharti	assert(chunk_name[0] != '\0');
319344747Savos	if (chunk_name == NULL || chunk_name[0] == '\0')
320154133Sharti		return;
321154133Sharti
322154856Sharti	HRDBG("ANALYZE chunk %s", chunk_name);
323154133Sharti
324154856Sharti	if ((entry = partition_entry_find_by_name(chunk_name)) == NULL)
325154856Sharti		if ((entry = partition_entry_create(ds_index,
326154856Sharti		    chunk_name)) == NULL)
327154133Sharti			return;
328154133Sharti
329154133Sharti	entry->flags |= HR_PARTITION_FOUND;
330154133Sharti
331154133Sharti	/* actual size may overflow the SNMP type */
332154856Sharti	k_size = chunk_size / 1024;
333154856Sharti	entry->size = (k_size > (off_t)INT_MAX ? INT_MAX : k_size);
334154133Sharti}
335154133Sharti
336154133Sharti/**
337154133Sharti * Start refreshing the partition table. A call to this function will
338154133Sharti * be followed by a call to handleDiskStorage() for every disk, followed
339154133Sharti * by a single call to the post_refresh function.
340154133Sharti */
341154133Shartivoid
342154133Shartipartition_tbl_pre_refresh(void)
343154133Sharti{
344160341Sharti	struct partition_entry *entry;
345154133Sharti
346154133Sharti	/* mark each entry as missing */
347154133Sharti	TAILQ_FOREACH(entry, &partition_tbl, link)
348154133Sharti		entry->flags &= ~HR_PARTITION_FOUND;
349154133Sharti}
350154133Sharti
351154133Sharti/**
352154856Sharti * Try to find a geom(4) class by its name. Returns a pointer to that
353154856Sharti * class if found NULL otherways.
354154133Sharti */
355154856Shartistatic struct gclass *
356154856Shartifind_class(struct gmesh *mesh, const char *name)
357154856Sharti{
358154856Sharti	struct gclass *classp;
359154856Sharti
360154856Sharti	LIST_FOREACH(classp, &mesh->lg_class, lg_class)
361154856Sharti		if (strcmp(classp->lg_name, name) == 0)
362154856Sharti			return (classp);
363154856Sharti	return (NULL);
364154856Sharti}
365154856Sharti
366154856Sharti/**
367154856Sharti * Process all MBR-type partitions from the given disk.
368154856Sharti */
369154856Shartistatic void
370154856Shartiget_mbr(struct gclass *classp, int32_t ds_index, const char *disk_dev_name)
371154856Sharti{
372154856Sharti	struct ggeom *gp;
373154856Sharti	struct gprovider *pp;
374154856Sharti	struct gconfig *conf;
375154856Sharti	long part_type;
376154856Sharti
377154856Sharti	LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
378154856Sharti		/* We are only interested in partitions from this disk */
379154856Sharti		if (strcmp(gp->lg_name, disk_dev_name) != 0)
380154856Sharti			continue;
381154856Sharti
382154856Sharti		/*
383154856Sharti		 * Find all the non-BSD providers (these are handled in get_bsd)
384154856Sharti		 */
385154856Sharti		LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
386154856Sharti			LIST_FOREACH(conf, &pp->lg_config, lg_config) {
387154856Sharti				if (conf->lg_name == NULL ||
388154856Sharti				    conf->lg_val == NULL ||
389154856Sharti				    strcmp(conf->lg_name, "type") != 0)
390154856Sharti					continue;
391154856Sharti
392154856Sharti				/*
393154856Sharti				 * We are not interested in BSD partitions
394154856Sharti				 * (ie ad0s1 is not interesting at this point).
395154856Sharti				 * We'll take care of them in detail (slice
396154856Sharti				 * by slice) in get_bsd.
397154856Sharti				 */
398154856Sharti				part_type = strtol(conf->lg_val, NULL, 10);
399154856Sharti				if (part_type == HR_FREEBSD_PART_TYPE)
400154856Sharti					break;
401154856Sharti				HRDBG("-> MBR PROVIDER Name: %s", pp->lg_name);
402154856Sharti				HRDBG("Mediasize: %jd",
403154856Sharti				    (intmax_t)pp->lg_mediasize / 1024);
404154856Sharti				HRDBG("Sectorsize: %u", pp->lg_sectorsize);
405154856Sharti				HRDBG("Mode: %s", pp->lg_mode);
406154856Sharti				HRDBG("CONFIG: %s: %s",
407154856Sharti				    conf->lg_name, conf->lg_val);
408154856Sharti
409154856Sharti				handle_chunk(ds_index, pp->lg_name,
410154856Sharti				    pp->lg_mediasize);
411154856Sharti			}
412154856Sharti		}
413154856Sharti	}
414154856Sharti}
415154856Sharti
416154856Sharti/**
417154856Sharti * Process all BSD-type partitions from the given disk.
418154856Sharti */
419154856Shartistatic void
420154856Shartiget_bsd_sun(struct gclass *classp, int32_t ds_index, const char *disk_dev_name)
421154856Sharti{
422154856Sharti	struct ggeom *gp;
423154856Sharti	struct gprovider *pp;
424154856Sharti
425154856Sharti	LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
426154856Sharti		/*
427154856Sharti		 * We are only interested in those geoms starting with
428154856Sharti		 * the disk_dev_name passed as parameter to this function.
429154856Sharti		 */
430154856Sharti		if (strncmp(gp->lg_name, disk_dev_name,
431154856Sharti		    strlen(disk_dev_name)) != 0)
432154856Sharti			continue;
433154856Sharti
434154856Sharti		LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
435154856Sharti			if (pp->lg_name == NULL)
436154856Sharti				continue;
437154856Sharti			handle_chunk(ds_index, pp->lg_name, pp->lg_mediasize);
438154856Sharti		}
439154856Sharti	}
440154856Sharti}
441154856Sharti
442154856Sharti/**
443154856Sharti * Called from the DiskStorage table for every row. Open the GEOM(4) framework
444154856Sharti * and process all the partitions in it.
445154856Sharti * ds_index is the index into the DiskStorage table.
446154856Sharti * This is done in two steps: for non BSD partitions the geom class "MBR" is
447154856Sharti * used, for our BSD slices the "BSD" geom class.
448154856Sharti */
449154133Shartivoid
450154133Shartipartition_tbl_handle_disk(int32_t ds_index, const char *disk_dev_name)
451154133Sharti{
452154856Sharti	struct gmesh mesh;	/* GEOM userland tree */
453154856Sharti	struct gclass *classp;
454154856Sharti	int error;
455154133Sharti
456154133Sharti	assert(disk_dev_name != NULL);
457154133Sharti	assert(ds_index > 0);
458154133Sharti
459160341Sharti	HRDBG("===> getting partitions for %s <===", disk_dev_name);
460154856Sharti
461154856Sharti	/* try to construct the GEOM tree */
462154856Sharti	if ((error = geom_gettree(&mesh)) != 0) {
463154856Sharti		syslog(LOG_WARNING, "cannot get GEOM tree: %m");
464154133Sharti		return;
465154133Sharti	}
466154133Sharti
467154856Sharti	/*
468154856Sharti	 * First try the GEOM "MBR" class.
469154856Sharti	 * This is needed for non-BSD slices (aka partitions)
470154856Sharti	 * on PC architectures.
471154856Sharti	 */
472154856Sharti	if ((classp = find_class(&mesh, "MBR")) != NULL) {
473154856Sharti		get_mbr(classp, ds_index, disk_dev_name);
474154856Sharti	} else {
475154856Sharti		HRDBG("cannot find \"MBR\" geom class");
476154856Sharti	}
477154856Sharti
478154856Sharti	/*
479154856Sharti	 * Get the "BSD" GEOM class.
480154856Sharti	 * Here we'll find all the info needed about the BSD slices.
481154856Sharti	 */
482154856Sharti	if ((classp = find_class(&mesh, "BSD")) != NULL) {
483154856Sharti		get_bsd_sun(classp, ds_index, disk_dev_name);
484154856Sharti	} else {
485154856Sharti		/* no problem on sparc64 */
486154856Sharti		HRDBG("cannot find \"BSD\" geom class");
487154856Sharti	}
488154856Sharti
489154856Sharti	/*
490154856Sharti	 * Get the "SUN" GEOM class.
491154856Sharti	 * Here we'll find all the info needed about the BSD slices.
492154856Sharti	 */
493154856Sharti	if ((classp = find_class(&mesh, "SUN")) != NULL) {
494154856Sharti		get_bsd_sun(classp, ds_index, disk_dev_name);
495154856Sharti	} else {
496154856Sharti		/* no problem on i386 */
497154856Sharti		HRDBG("cannot find \"SUN\" geom class");
498154856Sharti	}
499154856Sharti
500154856Sharti	geom_deletetree(&mesh);
501154133Sharti}
502154133Sharti
503154133Sharti/**
504154133Sharti * Finish refreshing the table.
505154133Sharti */
506154133Shartivoid
507154133Shartipartition_tbl_post_refresh(void)
508154133Sharti{
509154133Sharti	struct partition_entry *e, *etmp;
510154133Sharti
511154133Sharti	/*
512154133Sharti	 * Purge items that disappeared
513154133Sharti	 */
514154133Sharti	TAILQ_FOREACH_SAFE(e, &partition_tbl, link, etmp)
515154133Sharti		if (!(e->flags & HR_PARTITION_FOUND))
516154133Sharti			partition_entry_delete(e);
517154133Sharti}
518154133Sharti
519154133Sharti/*
520154133Sharti * Finalization routine for hrPartitionTable
521154133Sharti * It destroys the lists and frees any allocated heap memory
522154133Sharti */
523154133Shartivoid
524154133Shartifini_partition_tbl(void)
525154133Sharti{
526154133Sharti	struct partition_map_entry *m;
527154133Sharti
528160341Sharti	while ((m = STAILQ_FIRST(&partition_map)) != NULL) {
529154133Sharti		STAILQ_REMOVE_HEAD(&partition_map, link);
530154133Sharti		if(m->entry != NULL) {
531154133Sharti			TAILQ_REMOVE(&partition_tbl, m->entry, link);
532160341Sharti			free(m->entry->id);
533160341Sharti			free(m->entry->label);
534154133Sharti			free(m->entry);
535154133Sharti		}
536160341Sharti		free(m->id);
537154133Sharti		free(m);
538160341Sharti	}
539154133Sharti	assert(TAILQ_EMPTY(&partition_tbl));
540154133Sharti}
541154133Sharti
542154133Sharti/**
543154133Sharti * Called from the file system code to insert the file system table index
544154133Sharti * into the partition table entry. Note, that an partition table entry exists
545154133Sharti * only for local file systems.
546154133Sharti */
547154133Shartivoid
548154133Shartihandle_partition_fs_index(const char *name, int32_t fs_idx)
549154133Sharti{
550154133Sharti	struct partition_entry *entry;
551154133Sharti
552154133Sharti	if ((entry = partition_entry_find_by_label(name)) == NULL) {
553154133Sharti		HRDBG("%s IS MISSING from hrPartitionTable", name);
554154133Sharti		return;
555154133Sharti	}
556154133Sharti	HRDBG("%s [FS index = %d] IS in hrPartitionTable", name, fs_idx);
557154133Sharti	entry->fs_Index = fs_idx;
558154133Sharti}
559154133Sharti
560154133Sharti/*
561154133Sharti * This is the implementation for a generated (by our SNMP tool)
562154133Sharti * function prototype, see hostres_tree.h
563154133Sharti * It handles the SNMP operations for hrPartitionTable
564154133Sharti */
565154133Shartiint
566154133Shartiop_hrPartitionTable(struct snmp_context *ctx __unused, struct snmp_value *value,
567154133Sharti    u_int sub, u_int iidx __unused, enum snmp_op op)
568154133Sharti{
569154133Sharti	struct partition_entry *entry;
570154133Sharti
571154133Sharti	/*
572154133Sharti	 * Refresh the disk storage table (which refreshes the partition
573154133Sharti	 * table) if necessary.
574154133Sharti	 */
575154133Sharti	refresh_disk_storage_tbl(0);
576154133Sharti
577154133Sharti	switch (op) {
578154133Sharti
579154133Sharti	case SNMP_OP_GETNEXT:
580160341Sharti		if ((entry = NEXT_OBJECT_FUNC(&partition_tbl,
581160341Sharti		    &value->var, sub, partition_idx_cmp)) == NULL)
582154133Sharti			return (SNMP_ERR_NOSUCHNAME);
583154133Sharti
584160341Sharti		value->var.len = sub + 2;
585160341Sharti		value->var.subs[sub] = entry->index[0];
586160341Sharti		value->var.subs[sub + 1] = entry->index[1];
587160341Sharti
588154133Sharti		goto get;
589154133Sharti
590154133Sharti	case SNMP_OP_GET:
591160341Sharti		if ((entry = FIND_OBJECT_FUNC(&partition_tbl,
592160341Sharti		    &value->var, sub, partition_idx_cmp)) == NULL)
593154133Sharti			return (SNMP_ERR_NOSUCHNAME);
594154133Sharti		goto get;
595154133Sharti
596154133Sharti	case SNMP_OP_SET:
597160341Sharti		if ((entry = FIND_OBJECT_FUNC(&partition_tbl,
598160341Sharti		    &value->var, sub, partition_idx_cmp)) == NULL)
599154133Sharti			return (SNMP_ERR_NOT_WRITEABLE);
600154133Sharti		return (SNMP_ERR_NO_CREATION);
601154133Sharti
602154133Sharti	case SNMP_OP_ROLLBACK:
603154133Sharti	case SNMP_OP_COMMIT:
604154133Sharti		abort();
605154133Sharti	}
606154133Sharti	abort();
607154133Sharti
608154133Sharti  get:
609154133Sharti	switch (value->var.subs[sub - 1]) {
610154133Sharti
611154133Sharti	case LEAF_hrPartitionIndex:
612160341Sharti		value->v.integer = entry->index[1];
613154133Sharti		return (SNMP_ERR_NOERROR);
614154133Sharti
615154133Sharti	case LEAF_hrPartitionLabel:
616154133Sharti		return (string_get(value, entry->label, -1));
617154133Sharti
618154133Sharti	case LEAF_hrPartitionID:
619154133Sharti		return(string_get(value, entry->id, -1));
620154133Sharti
621154133Sharti	case LEAF_hrPartitionSize:
622154133Sharti		value->v.integer = entry->size;
623154133Sharti		return (SNMP_ERR_NOERROR);
624154133Sharti
625154133Sharti	case LEAF_hrPartitionFSIndex:
626154133Sharti		value->v.integer = entry->fs_Index;
627154133Sharti		return (SNMP_ERR_NOERROR);
628154133Sharti	}
629154133Sharti	abort();
630154133Sharti}
631