/*
*/
/*
* BSD 3 Clause License
*
* Copyright (c) 2007, The Storage Networking Industry Association.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* - Neither the name of The Storage Networking Industry Association (SNIA)
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
/* Copyright (c) 2007, The Storage Networking Industry Association. */
/*
* File history callback functions called by backup modules. NDMP file history
* ndmpd_file_history_dir() is called. During the file backup pass,
* ndmpd_file_history_node() is called. This model is appropriate for
* modules whose code is structured such that file name and file attribute
* included with the SDK uses the path based model.
*/
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "ndmpd.h"
#include <dirent.h>
#include <bitmap.h>
/* Figure an average of 32 bytes per path name */
/* Figure an average of 16 bytes per file name */
/*
* Each file history as a separate message to the client.
*/
static int ndmp_syncfh = 0;
/*
* ************************************************************************
* NDMP V2 HANDLERS
* ************************************************************************
*/
/*
* ndmpd_api_file_history_path_v2
*
* Add a file history path entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* name (input) - file name.
* NULL forces buffered data to be sent.
* file_stat (input) - file status pointer.
* fh_info (input) - data stream position of file data used during
* fast restore.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (0);
/*
* If the buffer does not have space
* for the current entry, send the buffered data to the client.
* A NULL name indicates that any buffered data should be sent.
*/
0) < 0) {
return (-1);
}
}
return (0);
sizeof (ndmp_fh_unix_path));
return (-1);
}
return (-1);
}
return (0);
}
/*
* ndmpd_api_file_history_dir_v2
*
* Add a file history dir entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* name (input) - file name.
* NULL forces buffered data to be sent.
* node (input) - file inode.
* parent (input) - file parent inode.
* Should equal node if the file is the root of
* the filesystem and has no parent.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (0);
/*
* If the buffer does not have space for the current entry,
* send the buffered data to the client. A NULL name indicates
* that any buffered data should be sent.
*/
0) < 0) {
return (-1);
}
}
return (0);
* sizeof (ndmp_fh_unix_dir));
return (-1);
}
return (-1);
}
return (0);
}
/*
* ndmpd_api_file_history_node_v2
*
* Add a file history node entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* node (input) - file inode.
* must match a node from a prior ndmpd_api_file_history_dir()
* call.
* file_stat (input) - file status pointer.
* 0 forces buffered data to be sent.
* fh_info (input) - data stream position of file data used during
* fast restore.
*
* Returns:
* 0 - success
* -1 - error.
*/
int
{
return (-1);
/*
* If the buffer does not have space
* for the current entry, send the buffered data to the client.
* A 0 file_stat pointer indicates that any buffered data should
* be sent.
*/
/*
* Need to send Dir entry as well. Since Dir entry is more than
* Node entry, we may send a Node entry that hasn't have
* its dir entry sent. Therefore, we need to flush Dir entry
* as well everytime the Dir entry is send.
*/
(void) ndmpd_api_file_history_dir_v2(session, 0, 0, 0);
0) < 0) {
return (-1);
}
}
return (0);
* sizeof (ndmp_fh_unix_node));
return (-1);
}
return (0);
}
/*
* ************************************************************************
* NDMP V3 HANDLERS
* ************************************************************************
*/
/*
* ndmpd_api_file_history_file_v3
*
* Add a file history file entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* name (input) - file name.
* NULL forces buffered data to be sent.
* file_stat (input) - file status pointer.
* fh_info (input) - data stream position of file data used during
* fast restore.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (0);
/*
* If the buffer does not have space
* for the current entry, send the buffered data to the client.
* A NULL name indicates that any buffered data should be sent.
*/
"Sending ndmp_fh_add_file request");
return (-1);
}
}
return (0);
return (-1);
}
return (-1);
}
ndmp_malloc(sizeof (char) * PATH_NAMEBUF_SIZE);
return (-1);
}
return (-1);
}
file_stat_entry->invalid = 0;
return (0);
}
/*
* ndmpd_api_file_history_dir_v3
*
* Add a file history dir entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* name (input) - file name.
* NULL forces buffered data to be sent.
* node (input) - file inode.
* parent (input) - file parent inode.
* Should equal node if the file is the root of
* the filesystem and has no parent.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (0);
/*
* If the buffer does not have space
* for the current entry, send the buffered data to the client.
* A NULL name indicates that any buffered data should be sent.
*/
"Sending ndmp_fh_add_dir request");
return (-1);
}
}
return (0);
return (-1);
}
return (-1);
}
ndmp_malloc(sizeof (char) * DIR_NAMEBUF_SIZE);
return (-1);
}
return (0);
}
/*
* ndmpd_api_file_history_node_v3
*
* Add a file history node entry to the buffer.
* History data is buffered until the buffer is filled.
* Full buffers are then sent to the client.
*
* Parameters:
* cookie (input) - session pointer.
* node (input) - file inode.
* must match a node from a prior ndmpd_api_file_history_dir()
* call.
* file_stat (input) - file status pointer.
* 0 forces buffered data to be sent.
* fh_info (input) - data stream position of file data used during
* fast restore.
*
* Returns:
* 0 - success
* -1 - error.
*/
int
{
return (0);
/*
* If the buffer does not have space
* for the current entry, send the buffered data to the client.
* A 0 file_stat pointer indicates that any buffered data should
* be sent.
*/
/*
* Need to send Dir entry as well. Since Dir entry is more
* than a Node entry, we may send a Node entry that hasn't
* had its Dir entry sent. Therefore, we need to flush Dir
* entry as well every time the Dir entry is sent.
*/
(void) ndmpd_api_file_history_dir_v3(session, 0, 0, 0);
NDMP_NO_ERR, (void *) &request, 0) < 0) {
"Sending ndmp_fh_add_node request");
return (-1);
}
}
return (0);
return (-1);
}
return (-1);
}
file_stat_entry->invalid = 0;
return (0);
}
/*
* ************************************************************************
* NDMP V4 HANDLERS
* ************************************************************************
*/
/*
* ndmpd_fhpath_v3_cb
*
* Callback function for file history path information
*/
int
{
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!path) {
err = -1;
err = -1;
} else
err = 0;
if (err != 0)
return (0);
err = 0;
}
err = -1;
} else {
char *p =
path);
}
}
return (err);
}
/*
* ndmpd_fhdir_v3_cb
*
* Callback function for file history dir information
*/
int
{
int nml;
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!dir) {
err = -1;
err = -1;
} else
err = 0;
if (err != 0)
return (0);
return (0);
/*
* Veritas net_backup accepts only 2 as the inode number of the backup
* root directory. The other way compares the path against the
* backup path which is slower.
*/
pino = ROOT_INODE;
else
/*
* There is nothing below this directory to be backed up.
* If there was, the bit for this directory would have
* been set. Backup root directory is exception. We
* always send the dir file history records of it.
*/
if (pino != ROOT_INODE &&
return (0);
}
return (-1);
pos = 0;
err = 0;
return (0);
do {
if (err != 0) {
break;
}
if (nml == 0)
break;
if (pino == ROOT_INODE) {
if (rootfs_dot_or_dotdot(nm))
ino = ROOT_INODE;
ino = ROOT_INODE;
}
continue;
/*
* If the entry is on exclusion list dont send the info
*/
continue;
}
if (err < 0) {
break;
}
/*
* This is a requirement by some DMA's (net_vault) that during
* the incremental backup, the node info should also be sent
* along with the dir info for all directories leading to a
* backed up file.
*/
if (ndmp_fhinode) {
if (err != 0) {
"Error looking up %s", nm);
break;
}
if (err < 0) {
break;
}
}
}
} while (err == 0);
return (err);
}
/*
* ndmpd_fhnode_v3_cb
*
* Callback function for file history node information
*/
int
{
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!dir) {
err = -1;
} else if (!file) {
err = -1;
} else if (!stp) {
err = -1;
err = -1;
} else {
err = 0;
}
if (err != 0)
return (0);
err = 0;
ino = ROOT_INODE;
} else
err = -1;
}
return (err);
}
/*
* ndmp_send_recovery_stat_v3
*
* Send the recovery status to the DMA
*/
int
{
int rv;
rv = -1;
if (!params) {
} else if (!params->mp_file_recovered_func) {
} else if (!nlp) {
} else if (idx < 0) {
} else {
}
return (rv);
}
/*
* ndmpd_path_restored_v3
*
* Send the recovery status and the information for the restored
* path.
*/
/*ARGSUSED*/
int
{
int rv;
if (!cbp) {
return (-1);
}
if (!name) {
return (-1);
}
if (!nlp) {
return (-1);
}
return (-1);
}
return (-1);
rv = 0;
/*
* Note: We should set the nm3_err here.
*/
0);
}
return (rv);
}
/*
* ndmpd_file_history_init
*
* Initialize file history variables.
* Note that the entry and name buffers are not allocated here.
* Since it is not know if the backup module will be sending file history
* buffers are not allocated until the first call to one of the file history
* entry functions is made. This way resources are only allocated as
* needed.
*
* Parameters:
* session (input) - session pointer.
*
* Returns:
* void
*/
void
{
/*
* V3.
*/
}
/*
* ndmpd_file_history_cleanup_v2
*
* Send (or discard) any buffered file history entries.
*
* Parameters:
* session (input) - session pointer.
* send_flag (input) - if TRUE buffered entries are sent.
* if FALSE buffered entries are discarded.
*
* Returns:
* void
*/
static void
{
(void) ndmpd_api_file_history_path_v2(session, 0, 0, 0);
(void) ndmpd_api_file_history_dir_v2(session, 0, 0, 0);
(void) ndmpd_api_file_history_node_v2(session, 0, 0, 0);
}
}
}
}
}
}
}
/*
* ndmpd_file_history_cleanup_v3
*
* Send (or discard) any buffered file history entries.
*
* Parameters:
* session (input) - session pointer.
* send_flag (input) - if TRUE buffered entries are sent.
* if FALSE buffered entries are discarded.
*
* Returns:
* void
*/
static void
{
(void) ndmpd_api_file_history_file_v3(session, 0, 0, 0);
(void) ndmpd_api_file_history_dir_v3(session, 0, 0, 0);
(void) ndmpd_api_file_history_node_v3(session, 0, 0, 0);
}
}
}
}
}
}
}
}
}
}
}
/*
* ndmpd_file_history_cleanup
*
* Send any pending posts and clean up
*/
void
{
switch (session->ns_protocol_version) {
case 1:
case 2:
break;
case 3:
case 4:
break;
default:
}
}
/*
* get_params
*
* Callbacks from LBR.
*/
static ndmpd_module_params_t *
{
return (NULL);
return (nlp->nlp_params);
}
/*
* fh_requested
*
* Check in LB parameters if file history is requested
*/
static boolean_t
{
return (FALSE);
}
}
/*
* ndmpd_file_history_path
*
* Generates file history path information posts
*
* Note:
* arguments of ndmpd_file_history_path(), ndmpd_file_history_dir(), and
* ndmpd_file_history_node() are NULL.
*/
/*ARGSUSED*/
int
{
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!path) {
err = -1;
} else if (!stp) {
err = -1;
} else
err = 0;
if (err != 0)
return (0);
err = 0;
err = -1;
}
return (err);
}
/*
* ndmpd_file_history_dir
*
* Generate file history directory information posts
*/
int
{
int nml;
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!dir) {
err = -1;
} else if (!stp) {
err = -1;
err = -1;
} else
err = 0;
if (err != 0)
return (0);
return (0);
/*
* Veritas net_backup accepts only 2 as the inode number of the backup
* root directory. The other way compares the path against the
* backup path which is slower.
*/
pino = ROOT_INODE;
else
/*
* There is nothing below this directory to be backed up.
* If there was, the bit for this directory would have
* been set. Backup root directory is exception. We
* always send the dir file history records of it.
*/
if (pino != ROOT_INODE &&
return (0);
}
return (0);
}
pos = 0;
err = 0;
return (0);
do {
if (err != 0) {
break;
}
if (nml == 0)
break;
if (pino == ROOT_INODE) {
if (rootfs_dot_or_dotdot(nm))
ino = ROOT_INODE;
ino = ROOT_INODE;
}
continue;
if (err < 0) {
break;
}
/*
* This is a requirement by some DMA's (net_vault) that during
* the incremental backup, the node info should also be sent
* along with the dir info for all directories leading to a
* backed up file.
*/
if (ndmp_fhinode) {
if (err != 0) {
"Error looking up %s", nm);
break;
}
if (err < 0) {
break;
}
}
}
} while (err == 0);
return (err);
}
/*
* ndmpd_file_history_node
*
* Generate file history node information posts
*/
/*ARGSUSED*/
int
{
int err;
if (!cbp) {
err = -1;
err = -1;
} else if (!dir) {
err = -1;
} else if (!file) {
err = -1;
} else if (!stp) {
err = -1;
err = -1;
} else
err = 0;
if (err != 0)
return (0);
err = 0;
ino = ROOT_INODE;
} else {
}
err = -1;
}
return (err);
}
/*
* ndmpd_path_restored
*
* Mark the specified path as a restored path
*/
/*ARGSUSED*/
int
{
int rv;
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
rv = 0;
}
return (rv);
}
/*
* dp_readdir
*
* Reads the entry of the directory and provides other information
* such as i-number, name, length and saves the dir entry position
* in a cookie for future calls.
*/
int
unsigned long *fileidp)
{
*n_namep = 0;
return (0);
}
return (errno);
}
return (0);
}