1167 lines
26 KiB
C
1167 lines
26 KiB
C
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1995, Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
#ident "xfs_query.c: $Revision: 1.7 $"
|
|
|
|
/*
|
|
* XFS queries on disks, filesystems and xlv objects.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <wctype.h>
|
|
#include <wsregexp.h>
|
|
#include <widec.h>
|
|
#include <string.h>
|
|
#include <bstring.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <sys/debug.h>
|
|
#include <sys/syssgi.h>
|
|
#include <sys/types.h>
|
|
#include <sys/uuid.h>
|
|
#include <sys/xlv_base.h>
|
|
#include <sys/xlv_tab.h>
|
|
#include <xlv_oref.h>
|
|
#include <xlv_utils.h>
|
|
#include <sys/xlv_vh.h>
|
|
#include <sys/xlv_attr.h>
|
|
#include <sys/dvh.h>
|
|
#include <pathnames.h>
|
|
#include <xlv_lab.h>
|
|
#include <tcl.h>
|
|
#include "xfs_fs_defs.h"
|
|
#include "xfs_query.h"
|
|
#include "xfs_xlv_query.h"
|
|
#include "xfs_disk_query_defs.h"
|
|
#include "xfs_fs_query_defs.h"
|
|
#include "xfs_info_defs.h"
|
|
#include "xfs_query_defs.h"
|
|
|
|
extern boolean_t isTableInitialized(void);
|
|
extern void init_admin(void);
|
|
extern fs_info_entry_t *xfs_info();
|
|
|
|
|
|
/*
|
|
* xfs_query_parse_regexp()
|
|
*
|
|
* This function compiles the given regular expression and parses the
|
|
* given value to check if it matches. The wide character based regular
|
|
* expression routines are used.
|
|
* Return Value: 0 if there is a match
|
|
* 1 otherwise
|
|
*/
|
|
|
|
short
|
|
xfs_query_parse_regexp(char* regexpn, char* value)
|
|
{
|
|
struct rexdata rex;
|
|
short result = 1;
|
|
long expbuf[BUFSIZ];
|
|
wchar_t *inputbuf;
|
|
wchar_t wregexpn[BUFSIZ];
|
|
wchar_t weof;
|
|
char eof = '\0';
|
|
|
|
if(value == NULL) {
|
|
return(1);
|
|
}
|
|
|
|
/* Parse the regular expression to handle the situation where
|
|
the regular expression is "*". This should match any
|
|
value. */
|
|
if (strcmp(regexpn,"\*")==0)
|
|
return(0);
|
|
|
|
inputbuf = (wchar_t*)
|
|
calloc(strlen((char*)value)+1,sizeof(wchar_t));
|
|
|
|
(void) mbstowcs(wregexpn,(char*)regexpn,strlen((char*)regexpn)+1);
|
|
(void) mbtowc(&weof, &eof, 1);
|
|
|
|
rex.sed = 0;
|
|
rex.str = wregexpn;
|
|
rex.sed = rex.err = 0;
|
|
|
|
if (!wsrecompile(&rex,expbuf,&expbuf[BUFSIZ],weof))
|
|
{
|
|
fprintf(stderr,"%s\n",wsreerr(rex.err));
|
|
}
|
|
else
|
|
{
|
|
(void) mbstowcs(inputbuf,value,strlen(value));
|
|
if (wsrematch(&rex,inputbuf,expbuf))
|
|
{
|
|
/* A reg expression like p* causes all strings to
|
|
be matched because zero or more instances
|
|
of p is a match! Hence, a check to see, if
|
|
the last character matching the regular
|
|
expression is different from the first
|
|
character of the regular expression
|
|
eliminates such spurious matches! */
|
|
|
|
if (&inputbuf[0] != rex.loc2)
|
|
result = 0;
|
|
}
|
|
}
|
|
|
|
free(inputbuf);
|
|
return(result);
|
|
}
|
|
|
|
|
|
/*
|
|
* create_fs_in_set()
|
|
* Adds references to all file system objects in the system.
|
|
*/
|
|
|
|
void
|
|
create_fs_in_set(query_set_t** in_set)
|
|
{
|
|
fs_info_entry_t *fs_info_list_entry=NULL;
|
|
fs_info_entry_t *fs_info_elm;
|
|
query_set_t *in_set_elm;
|
|
struct mntent *fs_mnt_info;
|
|
struct exportent *fs_exp_info;
|
|
char* msg=NULL;
|
|
|
|
fs_info_list_entry = xfs_info(NULL, &msg);
|
|
|
|
/* Clear any error/warning messages */
|
|
if (msg != NULL) {
|
|
free(msg);
|
|
msg = NULL;
|
|
}
|
|
|
|
while (fs_info_list_entry != NULL)
|
|
{
|
|
in_set_elm = (query_set_t*) malloc(sizeof(query_set_t));
|
|
ASSERT(in_set_elm!=NULL);
|
|
in_set_elm->type = FS_TYPE_QUERY;
|
|
|
|
in_set_elm->value.fs_ref = (fs_info_entry_t*)
|
|
malloc(sizeof(fs_info_entry_t));
|
|
ASSERT(in_set_elm->value.fs_ref!=NULL);
|
|
in_set_elm->value.fs_ref->info=fs_info_list_entry->info;
|
|
in_set_elm->value.fs_ref->fs_entry = NULL;
|
|
in_set_elm->value.fs_ref->mount_entry = NULL;
|
|
in_set_elm->value.fs_ref->export_entry = NULL;
|
|
|
|
/* Copy the fs_info_list_entry */
|
|
if (fs_info_list_entry->fs_entry!=NULL)
|
|
{
|
|
fs_mnt_info=in_set_elm->value.fs_ref->fs_entry=
|
|
(struct mntent*) malloc(sizeof(struct mntent));
|
|
ASSERT(fs_mnt_info!=NULL);
|
|
|
|
fs_mnt_info->mnt_fsname = (char*) malloc(strlen(
|
|
fs_info_list_entry->fs_entry->mnt_fsname)+1);
|
|
ASSERT(fs_mnt_info->mnt_fsname!=NULL);
|
|
strcpy(fs_mnt_info->mnt_fsname,
|
|
fs_info_list_entry->fs_entry->mnt_fsname);
|
|
|
|
fs_mnt_info->mnt_dir = (char*)malloc(strlen(
|
|
fs_info_list_entry->fs_entry->mnt_dir)+1);
|
|
ASSERT(fs_mnt_info->mnt_dir!=NULL);
|
|
strcpy(fs_mnt_info->mnt_dir,
|
|
fs_info_list_entry->fs_entry->mnt_dir);
|
|
|
|
fs_mnt_info->mnt_type = (char*)malloc(strlen(
|
|
fs_info_list_entry->fs_entry->mnt_type)+1);
|
|
ASSERT(fs_mnt_info->mnt_type!=NULL);
|
|
strcpy(fs_mnt_info->mnt_type,
|
|
fs_info_list_entry->fs_entry->mnt_type);
|
|
|
|
fs_mnt_info->mnt_opts = (char*)malloc(strlen(
|
|
fs_info_list_entry->fs_entry->mnt_opts)+1);
|
|
ASSERT(fs_mnt_info->mnt_opts!=NULL);
|
|
strcpy(fs_mnt_info->mnt_opts,
|
|
fs_info_list_entry->fs_entry->mnt_opts);
|
|
|
|
fs_mnt_info->mnt_freq =
|
|
fs_info_list_entry->fs_entry->mnt_freq;
|
|
fs_mnt_info->mnt_passno =
|
|
fs_info_list_entry->fs_entry->mnt_passno;
|
|
}
|
|
|
|
if (fs_info_list_entry->mount_entry!=NULL)
|
|
{
|
|
fs_mnt_info=in_set_elm->value.fs_ref->mount_entry=
|
|
(struct mntent*) malloc(sizeof(struct mntent));
|
|
ASSERT(fs_mnt_info!=NULL);
|
|
|
|
fs_mnt_info->mnt_fsname = (char*) malloc(strlen(
|
|
fs_info_list_entry->mount_entry->mnt_fsname)+1);
|
|
ASSERT(fs_mnt_info->mnt_fsname!=NULL);
|
|
strcpy(fs_mnt_info->mnt_fsname,
|
|
fs_info_list_entry->mount_entry->mnt_fsname);
|
|
|
|
fs_mnt_info->mnt_dir = (char*)malloc(strlen(
|
|
fs_info_list_entry->mount_entry->mnt_dir)+1);
|
|
ASSERT(fs_mnt_info->mnt_dir!=NULL);
|
|
strcpy(fs_mnt_info->mnt_dir,
|
|
fs_info_list_entry->mount_entry->mnt_dir);
|
|
|
|
fs_mnt_info->mnt_type = (char*)malloc(strlen(
|
|
fs_info_list_entry->mount_entry->mnt_type)+1);
|
|
ASSERT(fs_mnt_info->mnt_type!=NULL);
|
|
strcpy(fs_mnt_info->mnt_type,
|
|
fs_info_list_entry->mount_entry->mnt_type);
|
|
|
|
fs_mnt_info->mnt_opts = (char*)malloc(strlen(
|
|
fs_info_list_entry->mount_entry->mnt_opts)+1);
|
|
ASSERT(fs_mnt_info->mnt_opts!=NULL);
|
|
strcpy(fs_mnt_info->mnt_opts,
|
|
fs_info_list_entry->mount_entry->mnt_opts);
|
|
|
|
fs_mnt_info->mnt_freq =
|
|
fs_info_list_entry->mount_entry->mnt_freq;
|
|
fs_mnt_info->mnt_passno =
|
|
fs_info_list_entry->mount_entry->mnt_passno;
|
|
}
|
|
|
|
if (fs_info_list_entry->export_entry!=NULL)
|
|
{
|
|
fs_exp_info =
|
|
in_set_elm->value.fs_ref->export_entry =
|
|
(struct exportent*) malloc(sizeof(struct exportent));
|
|
ASSERT(fs_exp_info!=NULL);
|
|
|
|
if(fs_info_list_entry->export_entry->xent_dirname) {
|
|
fs_exp_info->xent_dirname=(char*)malloc(strlen(
|
|
fs_info_list_entry->export_entry->xent_dirname)+1);
|
|
strcpy(fs_exp_info->xent_dirname,
|
|
fs_info_list_entry->export_entry->xent_dirname);
|
|
}
|
|
else {
|
|
fs_exp_info->xent_dirname = NULL;
|
|
}
|
|
|
|
if(fs_info_list_entry->export_entry->xent_options) {
|
|
fs_exp_info->xent_options=(char*)malloc(strlen(
|
|
fs_info_list_entry->export_entry->xent_options)+1);
|
|
strcpy(fs_exp_info->xent_options,
|
|
fs_info_list_entry->export_entry->xent_options);
|
|
}
|
|
else {
|
|
fs_exp_info->xent_options = NULL;
|
|
}
|
|
}
|
|
|
|
in_set_elm->next = *in_set;
|
|
*in_set = in_set_elm;
|
|
|
|
fs_info_elm = fs_info_list_entry;
|
|
fs_info_list_entry = fs_info_list_entry->next;
|
|
delete_xfs_info_entry(fs_info_elm);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create_disks_in_set()
|
|
* Adds references to all the disks in the system.
|
|
*/
|
|
|
|
void
|
|
create_disks_in_set(query_set_t** in_set)
|
|
{
|
|
extern xlv_vh_entry_t *xlv_vh_list,
|
|
*nxlv_vh_list;
|
|
xlv_vh_entry_t *vh_entry;
|
|
query_set_t *in_set_elm;
|
|
|
|
if(! isTableInitialized()) {
|
|
init_admin();
|
|
}
|
|
|
|
for(vh_entry = xlv_vh_list;
|
|
vh_entry != NULL;
|
|
vh_entry = vh_entry->next) {
|
|
/* Create an entry for each disk */
|
|
in_set_elm = (query_set_t*) malloc(sizeof(query_set_t));
|
|
ASSERT(in_set_elm!=NULL);
|
|
in_set_elm->type = DISK_TYPE_QUERY;
|
|
in_set_elm->value.disk = vh_entry;
|
|
|
|
in_set_elm->next = *in_set;
|
|
*in_set = in_set_elm;
|
|
}
|
|
for(vh_entry = nxlv_vh_list;
|
|
vh_entry != NULL;
|
|
vh_entry = vh_entry->next) {
|
|
/* Create an entry for each disk */
|
|
in_set_elm = (query_set_t*) malloc(sizeof(query_set_t));
|
|
ASSERT(in_set_elm!=NULL);
|
|
in_set_elm->type = DISK_TYPE_QUERY;
|
|
in_set_elm->value.disk = vh_entry;
|
|
|
|
in_set_elm->next = *in_set;
|
|
*in_set = in_set_elm;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* create_xlv_in_set()
|
|
* Adds all instances of XLV objects known to the system to the
|
|
* in_set.
|
|
*/
|
|
|
|
void
|
|
create_xlv_in_set(query_set_t** in_set)
|
|
{
|
|
extern Tcl_HashTable xlv_obj_table;
|
|
Tcl_HashEntry *hash_entry;
|
|
Tcl_HashSearch search_ptr;
|
|
xlv_oref_t *oref;
|
|
xlv_query_set_t *xlv_query_set_elm;
|
|
query_set_t *in_set_elm;
|
|
|
|
init_admin();
|
|
|
|
hash_entry = Tcl_FirstHashEntry(&xlv_obj_table,&search_ptr);
|
|
while (hash_entry != NULL)
|
|
{
|
|
oref = (xlv_oref_t*) Tcl_GetHashValue(hash_entry);
|
|
ASSERT(oref!=NULL);
|
|
|
|
xlv_query_set_elm = (xlv_query_set_t*)
|
|
malloc(sizeof(xlv_query_set_t));
|
|
ASSERT(xlv_query_set_elm!=NULL);
|
|
xlv_query_set_elm->oref = oref;
|
|
xlv_query_set_elm->next = NULL;
|
|
|
|
in_set_elm = (query_set_t*) malloc(sizeof(query_set_t));
|
|
ASSERT(in_set_elm!=NULL);
|
|
in_set_elm->type = XLV_TYPE_QUERY;
|
|
in_set_elm->value.xlv_obj_ref = xlv_query_set_elm;
|
|
in_set_elm->value.xlv_obj_ref->creator = 0;
|
|
|
|
in_set_elm->next = *in_set;
|
|
*in_set = in_set_elm;
|
|
|
|
do {
|
|
oref = oref->next;
|
|
} while (oref!=NULL);
|
|
|
|
hash_entry = Tcl_NextHashEntry(&search_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create_in_set()
|
|
* This routine creates a set of all instances of XLV objects/disks
|
|
* and file systems known to the system.
|
|
*/
|
|
|
|
query_set_t*
|
|
create_in_set(void)
|
|
{
|
|
query_set_t* in_set = NULL;
|
|
|
|
/* Add the XLV objects to the in_set */
|
|
create_xlv_in_set(&in_set);
|
|
|
|
/* Add the Disks to the in_set */
|
|
create_disks_in_set(&in_set);
|
|
|
|
/* Add the file systems to the in_set */
|
|
create_fs_in_set(&in_set);
|
|
|
|
return(in_set);
|
|
}
|
|
|
|
|
|
/*
|
|
* set_xlv_obj_name()
|
|
* Converts the oref structure into a human readable name for the
|
|
* XLV object it represents.
|
|
*/
|
|
|
|
void
|
|
set_xlv_obj_name(query_set_t **element)
|
|
{
|
|
xlv_oref_t *oref;
|
|
xlv_tab_subvol_t *subvolume;
|
|
char *name_str;
|
|
|
|
if ((element == NULL) || (*element == NULL)) {
|
|
return;
|
|
}
|
|
|
|
oref = (*element)->value.xlv_obj_ref->oref;
|
|
name_str = (*element)->value.xlv_obj_ref->name;
|
|
|
|
if ((oref == NULL) || (name_str == NULL)) {
|
|
return;
|
|
}
|
|
|
|
switch(oref->obj_type) {
|
|
case XLV_OBJ_TYPE_VOL:
|
|
sprintf(name_str,XLV_OREF_VOL(oref)->name);
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_SUBVOL:
|
|
subvolume = XLV_OREF_SUBVOL(oref);
|
|
|
|
if(subvolume->subvol_type == XLV_SUBVOL_TYPE_LOG) {
|
|
strcpy(name_str, "log");
|
|
}
|
|
else if(subvolume->subvol_type==XLV_SUBVOL_TYPE_DATA) {
|
|
strcpy(name_str, "data");
|
|
}
|
|
else if(subvolume->subvol_type == XLV_SUBVOL_TYPE_RT) {
|
|
strcpy(name_str, "rt");
|
|
}
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_PLEX:
|
|
sprintf(name_str, "%s", XLV_OREF_PLEX(oref)->name);
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_VOL_ELMNT:
|
|
sprintf(name_str, "%s",
|
|
XLV_OREF_VOL_ELMNT(oref)->veu_name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* delete_fs_set_elm()
|
|
* Releases the memory allocated to save reference to file system objects.
|
|
*/
|
|
|
|
void
|
|
delete_fs_set_elm(query_set_t* elm)
|
|
{
|
|
if ((elm->type == FS_TYPE_QUERY) && (elm->value.fs_ref != NULL)) {
|
|
delete_xfs_info_entry(elm->value.fs_ref);
|
|
elm->value.fs_ref = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* delete_disk_set_elm()
|
|
* Releases the memory allocated to save the disk reference.
|
|
*/
|
|
|
|
void
|
|
delete_disk_set_elm(query_set_t* elm)
|
|
{
|
|
if ((elm->type == DISK_TYPE_QUERY) && (elm->value.disk != NULL)) {
|
|
free(elm->value.disk);
|
|
elm->value.disk = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* delete_xlv_set_elm()
|
|
* Releases the memory allocated to save the xlv object reference.
|
|
*/
|
|
|
|
void
|
|
delete_xlv_set_elm(query_set_t* elm)
|
|
{
|
|
if (elm->type == XLV_TYPE_QUERY) {
|
|
if (elm->value.xlv_obj_ref != NULL) {
|
|
if ((elm->value.xlv_obj_ref->oref != NULL) &&
|
|
(elm->value.xlv_obj_ref->creator == 1)) {
|
|
free(elm->value.xlv_obj_ref->oref);
|
|
elm->value.xlv_obj_ref->oref = NULL;
|
|
}
|
|
|
|
free(elm->value.xlv_obj_ref);
|
|
elm->value.xlv_obj_ref = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* delete_query_set()
|
|
* Deletes the query set element at a time by invoking the
|
|
* delete function of the appropriate element type.
|
|
*/
|
|
void
|
|
delete_query_set(query_set_t **set)
|
|
{
|
|
query_set_t *iter = *set;
|
|
|
|
while (iter != NULL) {
|
|
if (iter->type == XLV_TYPE_QUERY) {
|
|
delete_xlv_set_elm(iter);
|
|
}
|
|
else if (iter->type == FS_TYPE_QUERY) {
|
|
delete_fs_set_elm(iter);
|
|
}
|
|
|
|
*set = iter->next;
|
|
free(iter);
|
|
iter = *set;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* delete_in_set()
|
|
* Deletes the input set element at a time by invoking the
|
|
* delete function of the appropriate element type. All the
|
|
* resources allocated in building the input set are also
|
|
* released.
|
|
*/
|
|
void
|
|
delete_in_set(query_set_t **set)
|
|
{
|
|
query_set_t *iter = *set;
|
|
|
|
while (iter != NULL) {
|
|
if (iter->type == XLV_TYPE_QUERY) {
|
|
delete_xlv_set_elm(iter);
|
|
}
|
|
else if (iter->type == FS_TYPE_QUERY) {
|
|
delete_fs_set_elm(iter);
|
|
}
|
|
|
|
*set = iter->next;
|
|
free(iter);
|
|
iter = *set;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* IsElementInSet() - Checks if the element belongs to the set.
|
|
* Returns 0 if it exists in the set or else 1.
|
|
*/
|
|
|
|
int
|
|
IsElementInSet(query_set_t *element, query_set_t *set)
|
|
{
|
|
query_set_t *iter;
|
|
int elm_type;
|
|
int result = 1;
|
|
|
|
elm_type = element->type;
|
|
iter = set;
|
|
while (iter != NULL)
|
|
{
|
|
/* Compare similar types of objects! */
|
|
if (iter->type == elm_type)
|
|
{
|
|
if (elm_type == XLV_TYPE_QUERY)
|
|
{
|
|
if (strcmp(iter->value.xlv_obj_ref->name,
|
|
element->value.xlv_obj_ref->name)==0)
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
}
|
|
else if (elm_type == DISK_TYPE_QUERY)
|
|
{
|
|
if (strcmp(iter->value.disk->vh_pathname,
|
|
element->value.disk->vh_pathname)==0)
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
}
|
|
else if (elm_type == FS_TYPE_QUERY)
|
|
{
|
|
if ((iter->value.fs_ref->info & FS_FLAG)
|
|
&&(element->value.fs_ref->info & FS_FLAG)
|
|
&& (strcmp(iter->value.fs_ref->fs_entry->mnt_fsname,
|
|
element->value.fs_ref->fs_entry->mnt_fsname)==0))
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
else if ((iter->value.fs_ref->info & MNT_FLAG)
|
|
&&(element->value.fs_ref->info & MNT_FLAG)
|
|
&& (strcmp(iter->value.fs_ref->mount_entry->mnt_fsname,
|
|
element->value.fs_ref->mount_entry->mnt_fsname)==0))
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
iter = iter->next;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
/*
|
|
* logical_or_sets(setA,setB)
|
|
* The logical OR operation is performed on the sets A and B
|
|
* by checking if every element of setA is in setB. The result
|
|
* of the operation is stored in setA.
|
|
* setA = setA OR setB
|
|
*/
|
|
|
|
void
|
|
logical_or_sets(query_set_t** setA, query_set_t** setB)
|
|
{
|
|
query_set_t *element, *prev_element;
|
|
|
|
/* Traverse the setB adding the elements which don't belong to setA */
|
|
element = *setB;
|
|
prev_element = NULL;
|
|
while (element != NULL) {
|
|
if (IsElementInSet(element,*setA) != 0) {
|
|
/* Add this element to the setA */
|
|
if (prev_element == NULL) {
|
|
*setB = element->next;
|
|
}
|
|
else {
|
|
prev_element->next = element->next;
|
|
}
|
|
|
|
element->next = *setA;
|
|
*setA = element;
|
|
}
|
|
else {
|
|
prev_element = element;
|
|
}
|
|
|
|
if (prev_element == NULL) {
|
|
element = *setB;
|
|
}
|
|
else {
|
|
element = prev_element->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* logical_and_sets(setA,setB)
|
|
* The logical AND operation is performed on the sets A and B
|
|
* by checking if every element of setA is in setB. The result
|
|
* of the operation is stored in setA.
|
|
* setA = setA AND setB
|
|
*/
|
|
|
|
void
|
|
logical_and_sets(query_set_t** setA, query_set_t** setB)
|
|
{
|
|
query_set_t* element, *prev_element;
|
|
|
|
/* Traverse the setA deleting the elements which don't belong to setB */
|
|
element = *setA;
|
|
prev_element = NULL;
|
|
|
|
while (element != NULL) {
|
|
if (IsElementInSet(element,*setB) != 0) {
|
|
/* Remove this element from setA */
|
|
if (prev_element == NULL) {
|
|
*setA = element->next;
|
|
}
|
|
else {
|
|
prev_element->next = element->next;
|
|
}
|
|
|
|
free(element);
|
|
}
|
|
else {
|
|
prev_element = element;
|
|
}
|
|
|
|
if (prev_element == NULL) {
|
|
element = *setA;
|
|
}
|
|
else {
|
|
element = prev_element->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* query()
|
|
* This function resolves queries on the file system, disks and
|
|
* XLV objects in the system. The list of query clauses must be
|
|
* specified in the query_defn. A set of matching objects is returned
|
|
* on successful resolution of the query. If there is an error,
|
|
* NULL is returned.
|
|
*/
|
|
|
|
query_set_t *
|
|
query(query_clause_t *query_defn)
|
|
{
|
|
query_clause_t *query_clause = query_defn;
|
|
short query_clause_operator = QUERY_CLAUSE_OR_OPER;
|
|
query_set_t *in_set = NULL,
|
|
*out_set = NULL,
|
|
*result_set = NULL;
|
|
boolean_t need_xlv = B_TRUE,
|
|
need_disk = B_TRUE,
|
|
need_fs = B_TRUE;
|
|
|
|
while (query_clause != NULL) {
|
|
out_set = NULL;
|
|
|
|
if (query_clause->query_type == XLV_TYPE_QUERY) {
|
|
if(need_xlv) {
|
|
/* Add the XLV objects to the in_set */
|
|
create_xlv_in_set(&in_set);
|
|
need_xlv = B_FALSE;
|
|
}
|
|
xlv_query(query_clause, in_set, &out_set);
|
|
}
|
|
else if (query_clause->query_type == DISK_TYPE_QUERY) {
|
|
if(need_disk) {
|
|
/* Add the Disks to the in_set */
|
|
create_disks_in_set(&in_set);
|
|
need_disk = B_FALSE;
|
|
}
|
|
xfs_disk_query(query_clause, in_set, &out_set);
|
|
}
|
|
else if (query_clause->query_type == FS_TYPE_QUERY) {
|
|
if(need_fs) {
|
|
/* Add the file systems to the in_set */
|
|
create_fs_in_set(&in_set);
|
|
need_fs = B_FALSE;
|
|
}
|
|
xfs_fs_query(query_clause, in_set, &out_set);
|
|
}
|
|
|
|
if (query_clause_operator == QUERY_CLAUSE_OR_OPER) {
|
|
logical_or_sets(&result_set, &out_set);
|
|
delete_query_set(&out_set);
|
|
}
|
|
else if (query_clause_operator == QUERY_CLAUSE_AND_OPER) {
|
|
logical_and_sets(&result_set, &out_set);
|
|
delete_query_set(&out_set);
|
|
}
|
|
|
|
query_clause_operator = query_clause->query_clause_operator;
|
|
query_clause = query_clause->next;
|
|
}
|
|
|
|
delete_in_set(&in_set);
|
|
return(result_set);
|
|
}
|
|
|
|
|
|
/*
|
|
* lookup_attribute()
|
|
* Searches the list of known attributes for the specified attribute
|
|
* and returns the attribute id.
|
|
*/
|
|
|
|
int
|
|
lookup_attribute(char* attr_str)
|
|
{
|
|
int count=0;
|
|
|
|
while (count < XFS_QUERY_ATTR_LEN)
|
|
{
|
|
if (strcmp(xfs_query_attr_tab[count].attribute_name,
|
|
attr_str)==0)
|
|
return(xfs_query_attr_tab[count].attribute_id);
|
|
count++;
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/*
|
|
* build_query_clause()
|
|
* Constructs the query clause for disk attributes.
|
|
*/
|
|
|
|
query_clause_t*
|
|
build_query_clause(const char* query_type, const char* query_clause_str)
|
|
{
|
|
query_clause_t* query_clause=NULL;
|
|
char* token;
|
|
|
|
#ifdef DEBUG
|
|
printf("Constructing query clause %s\n", query_clause_str);
|
|
#endif
|
|
|
|
query_clause = (query_clause_t*) malloc(sizeof(query_clause_t));
|
|
ASSERT(query_clause!=NULL);
|
|
|
|
if (strcmp(query_type,FS_TYPE)==0)
|
|
query_clause->query_type = FS_TYPE_QUERY;
|
|
else if (strcmp(query_type,DISK_TYPE)==0)
|
|
query_clause->query_type = DISK_TYPE_QUERY;
|
|
else if (strcmp(query_type,VOL_TYPE)==0)
|
|
query_clause->query_type = XLV_TYPE_QUERY;
|
|
|
|
if ((token = strtok((char*)query_clause_str,"{:")) != NULL)
|
|
{
|
|
query_clause->attribute_id = lookup_attribute(token);
|
|
}
|
|
|
|
/* Fetch the operator */
|
|
if ((token = strtok(NULL,":")) != NULL) {
|
|
if (strcmp(token,"EQ")==0) {
|
|
query_clause->operator = QUERY_EQUAL;
|
|
}
|
|
else if (strcmp(token,"NEQ")==0) {
|
|
query_clause->operator = QUERY_NE;
|
|
}
|
|
else if (strcmp(token,"GT")==0) {
|
|
query_clause->operator = QUERY_GT;
|
|
}
|
|
else if (strcmp(token,"GE")==0) {
|
|
query_clause->operator = QUERY_GE;
|
|
}
|
|
else if (strcmp(token,"LT")==0) {
|
|
query_clause->operator = QUERY_LT;
|
|
}
|
|
else if (strcmp(token,"LE")==0) {
|
|
query_clause->operator = QUERY_LE;
|
|
}
|
|
else if (strcmp(token,"STRCMP")==0) {
|
|
query_clause->operator = QUERY_STRCMP;
|
|
}
|
|
else if (strcmp(token,"TRUE")==0) {
|
|
query_clause->operator = QUERY_TRUE;
|
|
}
|
|
else if (strcmp(token,"FALSE")==0) {
|
|
query_clause->operator = QUERY_FALSE;
|
|
}
|
|
}
|
|
|
|
/* Fetch the value to be compared */
|
|
if ((token = strtok(NULL,":")) != NULL)
|
|
{
|
|
query_clause->value = (char*)malloc(strlen(token)+1);
|
|
strcpy(query_clause->value,token);
|
|
}
|
|
|
|
/* Fetch the query clause operator */
|
|
if ((token = strtok(NULL,":")) != NULL)
|
|
{
|
|
if (strcmp(token,"OR")==0)
|
|
{
|
|
query_clause->query_clause_operator =
|
|
QUERY_CLAUSE_OR_OPER;
|
|
}
|
|
else if (strcmp(token,"AND")==0)
|
|
{
|
|
query_clause->query_clause_operator =
|
|
QUERY_CLAUSE_AND_OPER;
|
|
}
|
|
else if (strcmp(token,"EOQ")==0)
|
|
{
|
|
query_clause->query_clause_operator = EOQ;
|
|
}
|
|
}
|
|
|
|
query_clause->next = NULL;
|
|
|
|
return(query_clause);
|
|
}
|
|
|
|
|
|
/*
|
|
* build_query()
|
|
* Constructs the query by interpreting query_defn_str, query clause
|
|
* at a time.
|
|
*/
|
|
|
|
query_clause_t*
|
|
build_query(const char* query_type,const char* query_defn_str)
|
|
{
|
|
query_clause_t *query_defn=NULL;
|
|
query_clause_t *query_clause=NULL;
|
|
query_clause_t *last_query_clause=NULL;
|
|
char dup_query_defn_str[BUFSIZ];
|
|
char query_clause_str[BUFSIZ];
|
|
char *token;
|
|
char *ptr_next_token;
|
|
|
|
/* Make a copy of the query_defn_str as it mangled during strtok()*/
|
|
strcpy(dup_query_defn_str,query_defn_str);
|
|
|
|
token = strtok(dup_query_defn_str,"}");
|
|
while (token != NULL)
|
|
{
|
|
/* Save pointer to next token */
|
|
ptr_next_token = (token + strlen(token) + 1);
|
|
|
|
strcpy(query_clause_str,token);
|
|
query_clause = build_query_clause(query_type,query_clause_str);
|
|
|
|
/* Add the query clause to query_defn */
|
|
if (query_clause != NULL)
|
|
{
|
|
if (last_query_clause != NULL)
|
|
{
|
|
last_query_clause->next = query_clause;
|
|
query_clause->next = NULL;
|
|
last_query_clause = query_clause;
|
|
}
|
|
else
|
|
{
|
|
last_query_clause = query_defn = query_clause;
|
|
query_clause->next = NULL;
|
|
}
|
|
}
|
|
|
|
token = strtok(ptr_next_token,"}");
|
|
}
|
|
|
|
return(query_defn);
|
|
}
|
|
|
|
/*
|
|
* delete_query()
|
|
* Release the memory allocated for the query definition and results set.
|
|
*/
|
|
|
|
void
|
|
delete_query(query_clause_t* query_defn, query_set_t* set)
|
|
{
|
|
query_clause_t *query_clause, *next_query_clause;
|
|
query_set_t *elm, *next_elm;
|
|
|
|
/* Delete the query definition */
|
|
query_clause = query_defn;
|
|
while (query_clause != NULL)
|
|
{
|
|
if (query_clause->value != NULL)
|
|
{
|
|
free(query_clause->value);
|
|
}
|
|
|
|
next_query_clause = query_clause->next;
|
|
free(query_clause);
|
|
query_clause = next_query_clause;
|
|
}
|
|
|
|
/* Delete the results set */
|
|
elm = set;
|
|
while (elm != NULL)
|
|
{
|
|
if (elm->type == XLV_TYPE_QUERY)
|
|
{
|
|
if (elm->value.xlv_obj_ref != NULL)
|
|
{
|
|
if ((elm->value.xlv_obj_ref->oref != NULL) &&
|
|
(elm->value.xlv_obj_ref->creator == 1))
|
|
{
|
|
free(elm->value.xlv_obj_ref->oref);
|
|
}
|
|
|
|
free(elm->value.xlv_obj_ref);
|
|
}
|
|
}
|
|
else if (elm->type == DISK_TYPE_QUERY)
|
|
{
|
|
if (elm->value.disk != NULL)
|
|
{
|
|
free(elm->value.disk);
|
|
}
|
|
}
|
|
else if (elm->type == FS_TYPE_QUERY)
|
|
{
|
|
if (elm->value.fs_ref != NULL)
|
|
{
|
|
if (elm->value.fs_ref->fs_entry != NULL)
|
|
{
|
|
free(elm->value.fs_ref->fs_entry);
|
|
}
|
|
|
|
if (elm->value.fs_ref->export_entry != NULL)
|
|
{
|
|
free(elm->value.fs_ref->export_entry);
|
|
}
|
|
|
|
free(elm->value.fs_ref);
|
|
}
|
|
}
|
|
|
|
next_elm = elm->next;
|
|
free(elm);
|
|
elm = next_elm;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
/*
|
|
* display_results()
|
|
* Prints out the objects which satisfied the query.
|
|
*/
|
|
void
|
|
display_results(query_set_t* result_set)
|
|
{
|
|
query_set_t* elm;
|
|
|
|
if (result_set == NULL)
|
|
{
|
|
printf("\nNo matches to query\n");
|
|
}
|
|
else
|
|
{
|
|
printf("\nThe following objects matched the query\n");
|
|
}
|
|
|
|
elm = result_set;
|
|
while (elm != NULL)
|
|
{
|
|
if (elm->type == XLV_TYPE_QUERY)
|
|
{
|
|
printf("XLV Object %s\n",elm->value.xlv_obj_ref->name);
|
|
}
|
|
else if (elm->type == DISK_TYPE_QUERY)
|
|
{
|
|
printf("Disk %s\n",elm->value.disk->vh_pathname);
|
|
}
|
|
else if (elm->type == FS_TYPE_QUERY)
|
|
{
|
|
if (elm->value.fs_ref->fs_entry != NULL)
|
|
{
|
|
printf("File System %s\n",
|
|
elm->value.fs_ref->fs_entry->mnt_fsname);
|
|
}
|
|
else if (elm->value.fs_ref->mount_entry != NULL)
|
|
{
|
|
printf("File System %s\n",
|
|
elm->value.fs_ref->mount_entry->mnt_fsname);
|
|
}
|
|
}
|
|
|
|
elm = elm->next;
|
|
}
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
|
|
/*
|
|
* dump_results_to_buffer()
|
|
* Saves the object id's of the matching objects of the query
|
|
* in the buffer.
|
|
*/
|
|
|
|
void
|
|
dump_results_to_buffer(char *hostname, query_set_t *result_set, char **objs)
|
|
{
|
|
query_set_t *elm;
|
|
char *subtype;
|
|
|
|
for(elm = result_set; elm != NULL; elm = elm->next) {
|
|
if (elm->type == XLV_TYPE_QUERY)
|
|
{
|
|
/* Add the object type from the oref */
|
|
switch (elm->value.xlv_obj_ref->oref->obj_type)
|
|
{
|
|
case XLV_OBJ_TYPE_VOL:
|
|
subtype = VOL_TYPE;
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_PLEX:
|
|
subtype = PLEX_TYPE;
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_VOL_ELMNT:
|
|
subtype = VE_TYPE;
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_LOG_SUBVOL:
|
|
subtype = LOG_SUBVOL_TYPE;
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_DATA_SUBVOL:
|
|
subtype = DATA_SUBVOL_TYPE;
|
|
break;
|
|
|
|
case XLV_OBJ_TYPE_RT_SUBVOL:
|
|
subtype = RT_SUBVOL_TYPE;
|
|
break;
|
|
|
|
default:
|
|
subtype = UNKNOWN_TYPE;
|
|
break;
|
|
}
|
|
add_obj_to_buffer(objs, hostname, VOL_TYPE,
|
|
elm->value.xlv_obj_ref->name, subtype);
|
|
|
|
}
|
|
else if (elm->type == DISK_TYPE_QUERY)
|
|
{
|
|
add_obj_to_buffer(objs,hostname,DISK_TYPE,
|
|
elm->value.disk->vh_pathname,"0");
|
|
}
|
|
else if (elm->type == FS_TYPE_QUERY)
|
|
{
|
|
if (elm->value.fs_ref->fs_entry != NULL)
|
|
{
|
|
add_obj_to_buffer(objs,hostname,FS_TYPE,
|
|
elm->value.fs_ref->fs_entry->mnt_fsname,
|
|
elm->value.fs_ref->fs_entry->mnt_type);
|
|
}
|
|
else if (elm->value.fs_ref->mount_entry != NULL)
|
|
{
|
|
add_obj_to_buffer(objs,hostname,FS_TYPE,
|
|
elm->value.fs_ref->mount_entry->mnt_fsname,
|
|
elm->value.fs_ref->mount_entry->mnt_type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* xfs_query()
|
|
* Resolves a query on disks, filesystems or xlv objects in xfs.
|
|
* The query_type indicates the type of objects being queried.
|
|
* The query definition string, query_defn defines the query clauses
|
|
* (conditions). The matching object id's are stored in the string, objs.
|
|
* All error messages are logged in the buffer, msg.
|
|
*/
|
|
|
|
int
|
|
xfs_query(char *hostname,
|
|
const char *query_type,
|
|
const char *query_defn_str,
|
|
char **objs,
|
|
char **msg)
|
|
{
|
|
query_clause_t *query_defn;
|
|
query_set_t *results;
|
|
int returnVal = 0;
|
|
|
|
/* Construct the query definition */
|
|
if ((query_defn = build_query(query_type, query_defn_str)) == NULL)
|
|
{
|
|
returnVal = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Perform the query */
|
|
results = query(query_defn);
|
|
dump_results_to_buffer(hostname, results, objs);
|
|
|
|
#ifdef DEBUG
|
|
/* Display the results */
|
|
display_results(results);
|
|
#endif
|
|
|
|
/* Release all resources before quiting */
|
|
delete_query(query_defn, results);
|
|
}
|
|
|
|
return(returnVal);
|
|
}
|
|
|