1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 Damian Bogel.  All rights reserved.
  14  */
  15 
  16 /*
  17  * Library used to drive the fsd pseudo-device driver.
  18  */
  19 
  20 #include <fcntl.h>
  21 #include <libfsd.h>
  22 #include <string.h>
  23 #include <stropts.h>
  24 #include <sys/errno.h>
  25 #include <sys/fsd.h>
  26 #include <sys/stat.h>
  27 #include <sys/types.h>
  28 #include <unistd.h>
  29 
  30 __thread int fsd_errno;
  31 
  32 const char *
  33 fsd_strerr(int e)
  34 {
  35         switch (e) {
  36         case EFSD_NOERROR:
  37                 return ("no error");
  38         case EFSD_BAD_STAT:
  39                 return ("incorrect disturbance parameters");
  40         case EFSD_INTERNAL:
  41                 return ("internal library error");
  42         case EFSD_CANT_OPEN_DRIVER:
  43                 return ("cannot open fsd device");
  44         case EFSD_CANT_OPEN_MOUNTPOINT:
  45                 return ("cannot open mountpoint");
  46         case EFSD_ENTRY_NOT_FOUND:
  47                 return ("this vfs is not being disturbed");
  48         case EFSD_FAULT:
  49                 return ("bad pointer");
  50         case EFSD_UNKNOWN_ERROR:
  51         default:
  52                 return ("unknown error");
  53         }
  54 }
  55 
  56 static int
  57 fsd_ioctl_set_errno(int ioctl_ret)
  58 {
  59         extern int errno;
  60         int e;
  61 
  62         switch (ioctl_ret) {
  63         case 0:
  64                 fsd_errno = EFSD_NOERROR;
  65                 return (0);
  66 
  67         case (-1):
  68                 e = errno;
  69                 switch (e) {
  70                 case 0:
  71                         fsd_errno = EFSD_NOERROR;
  72                         break;
  73                 case EFAULT:
  74                         fsd_errno = EFSD_FAULT;
  75                         break;
  76                 case EINVAL:
  77                         fsd_errno = EFSD_INTERNAL;
  78                         break;
  79                 default:
  80                         fsd_errno = EFSD_UNKNOWN_ERROR;
  81                         break;
  82                 }
  83                 break;
  84         case FSD_ENTRY_NOT_FOUND:
  85                 fsd_errno = EFSD_ENTRY_NOT_FOUND;
  86                 break;
  87         case FSD_BAD_STAT:
  88                 fsd_errno = EFSD_BAD_STAT;
  89                 break;
  90         case FSD_BAD_FD:
  91                 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
  92                 break;
  93         default:
  94                 fsd_errno = EFSD_UNKNOWN_ERROR;
  95                 break;
  96         }
  97 
  98         return (-1);
  99 
 100 }
 101 
 102 int
 103 fsd_open()
 104 {
 105         int fd;
 106 
 107         if ((fd = open(FSD_DEV_PATH, O_RDWR)) == -1) {
 108                 fsd_errno = EFSD_CANT_OPEN_DRIVER;
 109                 return (-1);
 110         }
 111         return (fd);
 112 }
 113 
 114 void
 115 fsd_close(int fd)
 116 {
 117         (void) close(fd);
 118 }
 119 
 120 int
 121 fsd_enable(int fd)
 122 {
 123         return (fsd_ioctl_set_errno(ioctl(fd, FSD_ENABLE)));
 124 }
 125 
 126 int
 127 fsd_disable(int fd)
 128 {
 129         return (fsd_ioctl_set_errno(ioctl(fd, FSD_DISABLE)));
 130 }
 131 
 132 int
 133 fsd_disturb(int fd, const char *mntpt_path, fsd_stat_t *stat)
 134 {
 135         fsd_ioc_stat_t iocs;
 136         int error;
 137 
 138         if ((iocs.fsdis_mnt = open(mntpt_path, O_RDONLY)) == -1) {
 139                 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
 140                 return (-1);
 141         }
 142 
 143         (void) memcpy(&iocs.fsdis_stat, stat, sizeof (iocs.fsdis_stat));
 144 
 145         error = ioctl(fd, FSD_DISTURB, &iocs);
 146         (void) close(iocs.fsdis_mnt);
 147         return (fsd_ioctl_set_errno(error));
 148 }
 149 
 150 int
 151 fsd_disturb_off(int fd, const char *mntpt_path)
 152 {
 153         int error;
 154         int64_t mntfd;
 155 
 156         if ((mntfd = open(mntpt_path, O_RDONLY)) == -1) {
 157                 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
 158                 return (-1);
 159         }
 160 
 161         error = ioctl(fd, FSD_NODISTURB, &mntfd);
 162         (void) close(mntfd);
 163         return (fsd_ioctl_set_errno(error));
 164 }
 165 
 166 int
 167 fsd_newdisturb(int fd, fsd_stat_t *stat)
 168 {
 169         return (fsd_ioctl_set_errno(ioctl(fd, FSD_DISTURB_NEW, stat)));
 170 }
 171 
 172 int
 173 fsd_newdisturb_off(int fd)
 174 {
 175         return (fsd_ioctl_set_errno(ioctl(fd, FSD_NODISTURB_NEW)));
 176 }