/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_LIBSCF_PRIV_H
#define	_LIBSCF_PRIV_H

#pragma ident	"@(#)libscf_priv.h	1.11	04/12/08 SMI"

#include <libscf.h>
#include <unistd.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * NOTE
 *
 * The contents of this file are private to the implementation of Solaris
 * and are subject to change at any time without notice.
 */

#define	SCF_PG_GENERAL_TYPE		SCF_GROUP_FRAMEWORK
#define	SCF_PG_GENERAL_FLAGS		0

#define	SCF_PG_GENERAL_OVR_TYPE		SCF_GROUP_FRAMEWORK
#define	SCF_PG_GENERAL_OVR_FLAGS	SCF_PG_FLAG_NONPERSISTENT

#define	SCF_PG_OPTIONS_TYPE		SCF_GROUP_FRAMEWORK
#define	SCF_PG_OPTIONS_FLAGS		0

#define	SCF_PG_OPTIONS_OVR_TYPE		SCF_GROUP_FRAMEWORK
#define	SCF_PG_OPTIONS_OVR_FLAGS	SCF_PG_FLAG_NONPERSISTENT

#define	SCF_PG_RESTARTER_TYPE		SCF_GROUP_FRAMEWORK
#define	SCF_PG_RESTARTER_FLAGS		SCF_PG_FLAG_NONPERSISTENT

#define	SCF_PG_RESTARTER_ACTIONS_TYPE	SCF_GROUP_FRAMEWORK
#define	SCF_PG_RESTARTER_ACTIONS_FLAGS	SCF_PG_FLAG_NONPERSISTENT

#define	SCF_PROPERTY_LOGFILE		((const char *)"logfile")
#define	SCF_PROPERTY_ALT_LOGFILE	((const char *)"alt_logfile")

#define	SCF_LEGACY_SERVICE		((const char *)"smf/legacy_run")

#define	SCF_LEGACY_PROPERTY_NAME	((const char *)"name")
#define	SCF_LEGACY_PROPERTY_INODE	((const char *)"inode")
#define	SCF_LEGACY_PROPERTY_SUFFIX	((const char *)"suffix")

#define	SCF_FMRI_TYPE_SVC		0x1
#define	SCF_FMRI_TYPE_FILE		0x2

typedef struct scf_decoration_info {
	const char *sdi_name;
	scf_type_t sdi_type;
	scf_value_t *sdi_value;		/* can be SCF_DECORATE_CLEAR */
} scf_decoration_info_t;

typedef int (*scf_decoration_func)(const scf_decoration_info_t *, void *);

/*
 * calls a callback function for each decoration on the handle.  If the
 * callback returns 0, the iteration stops and returns 0.  If the callback
 * returns a non-zero value, the iteration continues.  After full completion,
 * 1 is returned.  On error, -1 is returned.
 */
int _scf_handle_decorations(scf_handle_t *, scf_decoration_func *,
    scf_value_t *, void *);

/*
 * wait for a change to the propertygroup -- may return early.
 * For now, only one of these can be outstanding at a time.
 *
 * The second argument is how long, in seconds, to wait for a response.
 *
 * Returns SCF_COMPLETE on timeout, -1 on error, and SCF_SUCCESS in every
 * other case.  You must call scf_pg_update() to see if the object has
 * actually changed.
 */
int _scf_pg_wait(scf_propertygroup_t *, int);

/*
 * set up notifications for changes to a class of property groups (by name
 * and type)
 *
 * Only one thread can be sleeping in _scf_notify_wait() -- others will
 * fail.  Deletions give an fmri in the output path.
 *
 * These do not survive unbind()->bind() -- in fact, that is currently the
 * only way to clear them.
 */
int _scf_notify_add_pgname(scf_handle_t *, const char *);
int _scf_notify_add_pgtype(scf_handle_t *, const char *);
int _scf_notify_wait(scf_propertygroup_t *, char *, size_t);

/*
 * Internal interfaces for snapshot creation:
 *	_scf_snapshot_take_new(), _scf_snapshot_take_new_named(), and
 *	_scf_snapshot_take_attach() create a set of snaplevels
 *	containing frozen versions of both the instance's property groups and
 *	its parent service's property groups. _scf_snapshot_take_new() and
 *	_scf_snapshot_take_new_named() create a new snapshot to which the
 *	new snaplevels are attached, while _scf_snapshot_take_attach()
 *	attaches the new snaplevels to a pre-existing snapshot.
 *
 *	_scf_snapshot_take_new_named() records the passed in names into the
 *	snaplevel instead of the instance and service name.  This creates
 *	an inconsistency, which should be resolved by using
 *	_scf_snapshot_attach() to attach the new snaplevels to a snapshot
 *	underneath the appropriate instance.  The first snapshot can
 *	then be deleted.
 *
 *	_scf_snapshot_attach(snap1, snap2) points snap2 at the snaplevels
 *	pointed to by snap1.  After a call to either
 *	_scf_snapshot_take_attach(snap1, snap2) or
 *	_scf_snapshot_attach(inst, snap), scf_snapshot_update() will be
 *	required for any open references to snap or snap2 to see the new
 *	snaplevels.
 *
 *	_scf_snapshot_delete() deletes the snapshot object.  While
 *	snaplevels, being only loosely connected to snapshots, stay
 *	around until they are no longer referenced, any references *through
 *	this snapshot object* will be invalidated.
 *
 * _scf_snapshot_take_new() can fail with at least _HANDLE_MISMATCH,
 * _CONNECTION_BROKEN, _INVALID_ARGUMENT, _NO_RESOURCES, _PERMISSION_DENIED,
 * _NOT_SET, _EXISTS.
 *
 * _scf_snapshot_take_new_named() can fail with at least _HANDLE_MISMATCH,
 * _CONNECTION_BROKEN, _INVALID_ARGUMENT, _NO_RESOURCES, _PERMISSION_DENIED,
 * _NOT_SET, _EXISTS.
 *
 * _scf_snapshot_take_attach() can fail with _CONNECTION_BROKEN, _NOT_SET,
 * _PERMISSION_DENIED, _NO_RESOURCES, _INVALID_ARGUMENT.
 *
 * _scf_snapshot_attach() can fail with _HANDLE_MISMATCH, _CONNECTION_BROKEN,
 * _NOT_SET, _NO_RESOURCES, _PERMISSION_DENIED.
 */
int _scf_snapshot_take_new(scf_instance_t *, const char *, scf_snapshot_t *);
int _scf_snapshot_take_new_named(scf_instance_t *,
    const char *, const char *, const char *, scf_snapshot_t *);
int _scf_snapshot_take_attach(scf_instance_t *, scf_snapshot_t *);
int _scf_snapshot_attach(scf_snapshot_t *, scf_snapshot_t *);
int _scf_snapshot_delete(scf_snapshot_t *);

/*
 * Destructively portions up the first argument into the different portions
 * of a svc: fmri, and returns pointers to the applicable portions.  Omitted
 * portions are set to NULL, except for the scope, which is set to the
 * default local scope if not specified.
 *
 * Parsing is attempted in the order of: svc:, file:. The identified type
 * of the service is returned in the second argument and may take a value
 * of: SCF_FMRI_TYPE_SVC or SCF_FMRI_TYPE_FILE.
 *
 * Note that some of the returned pointers (in particular the scope) may not
 * point into the passed buffer.
 */
int scf_parse_fmri(char *, int *, const char **, const char **, const char **,
    const char **, const char **);

int scf_parse_svc_fmri(char *, const char **, const char **, const char **,
    const char **, const char **);

int scf_parse_file_fmri(char *fmri, const char **scope, const char **path);

ssize_t scf_canonify_fmri(const char *, char *, size_t);

const char *scf_type_to_string(scf_type_t);
scf_type_t scf_string_to_type(const char *);

int _smf_refresh_instance_i(scf_instance_t *);

/*
 * Walks all the instances matching a given fmri list.  Each fmri in the array
 * can be one of the following:
 *
 * 	- Full instance name
 * 	- Full service name
 * 	- Full property group or property name
 * 	- Partial service or instance name
 * 	- A globbed pattern
 *
 * The matching rules for partial fmris are a slightly more complex.  We allow
 * for any substring anchored at the end of the instance or service name,
 * provided it begins with a complete element in the fmri.  For example, given
 * the fmri "svc:/system/filesystem/local:default", any of the following would
 * be acceptable matches: 'default', 'local', 'local:default',
 * 'filesystem/local'.  The following would not be acceptable:
 * 'system/filesystem', 'filesystem/loc', 'system/local'.  Possible flag values:
 *
 * 	SCF_WALK_MULTIPLE	Allow individual arguments to correspond to
 * 				multiple instances.
 *
 * 	SCF_WALK_LEGACY		Walk legacy services (indicated by a non-NULL
 * 				propery group).
 *
 * 	SCF_WALK_SERVICE	If the user specifies a service, pass the
 * 				service to the callback without iterating over
 * 				its instances.
 *
 * 	SCF_WALK_PROPERTY	Allow FMRIs which match property groups or
 * 				individual properties.  Incompatible with
 * 				SCF_WALK_LEGACY.
 *
 * 	SCF_WALK_NOINSTANCE	Walk only services.  Must be used in
 * 				conjunction with SCF_WALK_SERVICE.
 *
 * 	SCF_WALK_EXPLICIT	Walk only services if the match is exact
 *				else return instances. Must be used in
 *				conjunction with SCF_WALK_SERVICE.
 *
 * If no arguments are given, then all instances in the service graph are
 * walked.
 *
 * The second to last parameter is set to UU_EXIT_FATAL if one of the arguments
 * is an invalid FMRI or matches multiple FMRIs when SCF_WALK_MULTIPLE is not
 * set.
 *
 * The last parameter is a user-supplied error function that is called when
 * reporting invalid arguments.
 */

#define	SCF_WALK_MULTIPLE	0x01
#define	SCF_WALK_LEGACY		0x02
#define	SCF_WALK_SERVICE	0x04
#define	SCF_WALK_PROPERTY	0x08
#define	SCF_WALK_NOINSTANCE	0x10
#define	SCF_WALK_EXPLICIT	0x20

typedef struct scf_walkinfo {
	const char		*fmri;
	scf_scope_t		*scope;
	scf_service_t		*svc;
	scf_instance_t		*inst;
	scf_propertygroup_t	*pg;
	scf_property_t		*prop;
	int			count;	/* svcprop special */
} scf_walkinfo_t;

typedef int (*scf_walk_callback)(void *, scf_walkinfo_t *);

scf_error_t scf_walk_fmri(scf_handle_t *, int, char **, int,
    scf_walk_callback, void *, int *, void (*)(const char *, ...));

/*
 * Requests a backup of the repository with a particular name, which
 * can be any alphabetic string.  Only privileged users can do this.
 *
 * Can fail with:
 *	_NOT_BOUND, _CONNECTION_BROKEN, _PERMISSION_DENIED, _INVALID_ARGUMENT,
 *	_INTERNAL (path too long, or the backup failed for an odd reason),
 *	_BACKEND_READONLY (filesystem is still read-only)
 */
int _scf_request_backup(scf_handle_t *, const char *);

#ifdef	__cplusplus
}
#endif

#endif	/* _LIBSCF_PRIV_H */
