/*
* smbinfo
*
* Copyright (C) Ronnie Sahlberg (lsahlberg@redhat.com) 2018
* Copyright (C) Aurelien Aptel (aaptel@suse.com) 2018
*
* Display SMB-specific file information using cifs IOCTL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <endian.h>
#include <errno.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <inttypes.h>
#define CIFS_IOCTL_MAGIC 0xCF
/* query_info flags */
#define PASSTHRU_QUERY_INFO 0x00000000
#define PASSTHRU_FSCTL 0x00000001
struct smb_query_info {
uint32_t info_type;
uint32_t file_info_class;
uint32_t additional_information;
uint32_t flags;
uint32_t input_buffer_length;
uint32_t output_buffer_length;
/* char buffer[]; */
} __packed;
#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
#define INPUT_BUFFER_LENGTH 16384
int verbose;
static void
usage(char *name)
{
fprintf(stderr, "Usage: %s [-V] <command> <file>\n"
"-V for verbose output\n"
"-h display this help text\n"
"-v print smbinfo version\n"
"Commands are\n"
" fileaccessinfo:\n"
" Prints FileAccessInfo for a cifs file.\n"
" filealigninfo:\n"
" Prints FileAlignInfo for a cifs file.\n"
" fileallinfo:\n"
" Prints FileAllInfo for a cifs file.\n"
" filebasicinfo:\n"
" Prints FileBasicInfo for a cifs file.\n"
" fileeainfo:\n"
" Prints FileEAInfo for a cifs file.\n"
" filefsfullsizeinfo:\n"
" Prints FileFsFullSizeInfo for a cifs share.\n"
" fileinternalinfo:\n"
" Prints FileInternalInfo for a cifs file.\n"
" filemodeinfo:\n"
" Prints FileModeInfo for a cifs file.\n"
" filepositioninfo:\n"
" Prints FilePositionInfo for a cifs file.\n"
" filestandardinfo:\n"
" Prints FileStandardInfo for a cifs file.\n"
" fsctl-getobjid:\n"
" Prints the objectid of the file and GUID of the underlying volume.\n"
" list-snapshots:\n"
" List the previous versions of the volume that backs this file.\n"
" quota:\n"
" Prints the quota for a cifs file.\n"
" secdesc:\n"
" Prints the security descriptor for a cifs file.\n",
name);
exit(1);
}
static void
short_usage(char *name)
{
fprintf(stderr, "Usage: %s [-v] [-V] <command> <file>\n"
"Try 'smbinfo -h' for more information.\n", name);
exit(1);
}
static void
win_to_timeval(uint64_t smb2_time, struct timeval *tv)
{
tv->tv_usec = (smb2_time / 10) % 1000000;
tv->tv_sec = (smb2_time - 116444736000000000) / 10000000;
}
struct bit_string {
unsigned int bit;
char *string;
};
struct bit_string directory_access_mask[] = {
{ 0x00000001, "LIST_DIRECTORY" },
{ 0x00000002, "ADD_FILE" },
{ 0x00000004, "ADD_SUBDIRECTORY" },
{ 0x00000008, "READ_EA" },
{ 0x00000010, "WRITE_EA" },
{ 0x00000020, "TRAVERSE" },
{ 0x00000040, "DELETE_CHILD" },
{ 0x00000080, "READ_ATTRIBUTES" },
{ 0x00000100, "WRITE_ATTRIBUTES" },
{ 0x00010000, "DELETE" },
{ 0x00020000, "READ_CONTROL" },
{ 0x00040000, "WRITE_DAC" },
{ 0x00080000, "WRITE_OWNER" },
{ 0x00100000, "SYNCHRONIZER" },
{ 0x01000000, "ACCESS_SYSTEM_SECURITY" },
{ 0x02000000, "MAXIMUM_ALLOWED" },
{ 0x10000000, "GENERIC_ALL" },
{ 0x20000000, "GENERIC_EXECUTE" },
{ 0x40000000, "GENERIC_WRITE" },
{ 0x80000000, "GENERIC_READ" },
{ 0, NULL }
};
struct bit_string file_access_mask[] = {
{ 0x00000001, "READ_DATA" },
{ 0x00000002, "WRITE_DATA" },
{ 0x00000004, "APPEND_DATA" },
{ 0x00000008, "READ_EA" },
{ 0x00000010, "WRITE_EA" },
{ 0x00000020, "EXECUTE" },
{ 0x00000040, "DELETE_CHILD" },
{ 0x00000080, "READ_ATTRIBUTES" },
{ 0x00000100, "WRITE_ATTRIBUTES" },
{ 0x00010000, "DELETE" },
{ 0x00020000, "READ_CONTROL" },
{ 0x00040000, "WRITE_DAC" },
{ 0x00080000, "WRITE_OWNER" },
{ 0x00100000, "SYNCHRONIZER" },
{ 0x01000000, "ACCESS_SYSTEM_SECURITY" },
{ 0x02000000, "MAXIMUM_ALLOWED" },
{ 0x10000000, "GENERIC_ALL" },
{ 0x20000000, "GENERIC_EXECUTE" },
{ 0x40000000, "GENERIC_WRITE" },
{ 0x80000000, "GENERIC_READ" },
{ 0, NULL }
};
static void
print_bits(uint32_t mask, struct bit_string *bs)