/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright 2016 Martin Matuska. All rights reserved.
*/
#include <synch.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <libzfs.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
#include "smbd.h"
/*
* This file supports three basic functions that all use the
* the zfs_iter_snapshots function to get the snapshot info
* from ZFS. If the filesystem is not ZFS, the an error is sent
* to the caller (door functions in this case) with the count of
* zero in the case of smbd_vss_get_count. Each function
* is expecting a path that is the root of the dataset.
* The basic idea is to define a structure for the data and
* an iterator function that will be called for every snapshot
* in the dataset that was opened. The iterator function gets
* a zfs_handle_t(that needs to be closed) for the snapshot
* and a pointer to the structure of data defined passed to it.
* If the iterator function returns a non-zero value, no more
* snapshots will be processed. There is no guarantee in the
* order in which the snapshots are processed.
*
* The structure of this file is:
* Three structures that are used between the iterator functions
* and "main" functions
* The 3 "main" functions
* Support functions
* The 3 iterator functions
*/
/*
* The maximum number of snapshots returned per request.
*/
static int smbd_vss_cmp_time(const void *a, const void *b);
typedef struct smbd_vss_count {
int vc_count;
/*
* gd_count how many @GMT tokens are expected
* gd_return_count how many @GMT tokens are being returned
* gd_gmt_array array of the @GMT token with max size of gd_count
*/
typedef struct smbd_vss_get_uint64_date {
int gd_count;
int gd_return_count;
typedef struct smbd_vss_map_gmttoken {
char *mg_snapname;
/*
* path - path of the dataset
* count - return value of the number of snapshots for the dataset
*/
int
{
*count = 0;
return (-1);
return (-1);
return (-1);
}
(void *)&vss_count);
return (0);
}
/*
* path - is the path of the dataset
* count - is the maxium number of GMT tokens allowed to be returned
* return_count - is how many should be returned
* num_gmttokens - how many gmttokens in gmttokenp (0 if error)
* gmttokenp - array of @GMT tokens (even if zero, elements still need
* to be freed)
*/
void
{
int i;
*return_count = 0;
*num_gmttokens = 0;
if (count == 0)
return;
if (count > SMBD_VSS_SNAPSHOT_MAX)
return;
return;
}
return;
}
return;
}
smbd_vss_iterate_get_uint64_date, (void *)&vss_uint64_date);
/*
* Sort the list since neither zfs nor the client sorts it.
*/
sizeof (uint64_t), smbd_vss_cmp_time);
for (i = 0; i < vss_uint64_date.gd_return_count; i++) {
if (*gmttokenp)
else
timep++;
gmttokenp++;
}
}
static const char
/*
* path - path of the dataset for the operation
* gmttoken - the @GMT token to be looked up
* toktime - time_t used if gmttoken == NULL
* snapname - the snapshot name to be returned [MAXPATHLEN]
*
* Here we are going to get the snapshot name from the @GMT token
* The snapname returned by ZFS is : <dataset name>@<snapshot name>
* So we are going to make sure there is the @ symbol in
* the right place and then just return the snapshot name
*/
int
char *snapname)
{
char *zsnap;
const char *lsnap;
}
*snapname = '\0';
return (-1);
return (-1);
return (-1);
}
(void *)&vss_map_gmttoken);
/* compare the zfs snapshot name and the local snap name */
zsnap++;
lsnap++;
}
/* Now we should be passed the dataset name */
zsnap++;
} else {
*snapname = '\0';
}
return (0);
}
static void
{
struct tm t;
smbd_vss_gmttoken_fmt, &t);
}
static int
smbd_vss_cmp_time(const void *a, const void *b)
{
return (1);
return (0);
return (-1);
}
/*
* ZFS snapshot iterator to count snapshots.
* Note: libzfs expects us to close the handle.
* Return 0 to continue iterating or non-zreo to terminate the iteration.
*/
static int
{
return (0);
}
return (-1);
}
/*
* ZFS snapshot iterator to get snapshot creation time.
* Note: libzfs expects us to close the handle.
* Return 0 to continue iterating or non-zreo to terminate the iteration.
*/
static int
{
int count;
return (0);
}
return (-1);
}
/*
* ZFS snapshot iterator to map a snapshot creation time to a token.
* Note: libzfs expects us to close the handle.
* Return 0 to continue iterating or non-zreo to terminate the iteration.
*/
static int
{
/* we found a match, do not process anymore snapshots */
return (-1);
}
return (0);
}