LCOV - code coverage report
Current view: top level - source4/ntvfs/posix - pvfs_fsinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 96 112 85.7 %
Date: 2024-02-28 12:06:22 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    POSIX NTVFS backend - fsinfo
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "vfs_posix.h"
      24             : #include "librpc/gen_ndr/xattr.h"
      25             : #include "librpc/ndr/libndr.h"
      26             : 
      27             : /* We use libblkid out of e2fsprogs to identify UUID of a volume */
      28             : #ifdef HAVE_LIBBLKID
      29             : #include <blkid/blkid.h>
      30             : #endif
      31             : 
      32          15 : static NTSTATUS pvfs_blkid_fs_uuid(struct pvfs_state *pvfs, struct stat *st, struct GUID *uuid)
      33             : {
      34             : #ifdef HAVE_LIBBLKID
      35             :         NTSTATUS status;
      36             :         char *uuid_value = NULL;
      37             :         char *devname = NULL;
      38             : 
      39             :         devname = blkid_devno_to_devname(st->st_dev);
      40             :         if (!devname) {
      41             :                 ZERO_STRUCTP(uuid);
      42             :                 return NT_STATUS_OK;
      43             :         }
      44             : 
      45             :         uuid_value = blkid_get_tag_value(NULL, "UUID", devname);
      46             :         free(devname);
      47             :         if (!uuid_value) {
      48             :                 ZERO_STRUCTP(uuid);
      49             :                 return NT_STATUS_OK;
      50             :         }
      51             : 
      52             :         status = GUID_from_string(uuid_value, uuid);
      53             :         free(uuid_value);
      54             :         if (!NT_STATUS_IS_OK(status)) {
      55             :                 ZERO_STRUCTP(uuid);
      56             :                 return NT_STATUS_OK;
      57             :         }
      58             :         return NT_STATUS_OK;
      59             : #else
      60          15 :         ZERO_STRUCTP(uuid);
      61          15 :         return NT_STATUS_OK;
      62             : #endif
      63             : }
      64             : 
      65          15 : static NTSTATUS pvfs_cache_base_fs_uuid(struct pvfs_state *pvfs, struct stat *st)
      66             : {
      67           0 :         NTSTATUS status;
      68           0 :         struct GUID uuid;
      69             : 
      70          15 :         if (pvfs->base_fs_uuid) return NT_STATUS_OK;
      71             : 
      72          15 :         status = pvfs_blkid_fs_uuid(pvfs, st, &uuid);
      73          15 :         NT_STATUS_NOT_OK_RETURN(status);
      74             : 
      75          15 :         pvfs->base_fs_uuid = talloc(pvfs, struct GUID);
      76          15 :         NT_STATUS_HAVE_NO_MEMORY(pvfs->base_fs_uuid);
      77          15 :         *pvfs->base_fs_uuid = uuid;
      78             : 
      79          15 :         return NT_STATUS_OK;
      80             : }
      81             : /*
      82             :   return filesystem space info
      83             : */
      84        4195 : NTSTATUS pvfs_fsinfo(struct ntvfs_module_context *ntvfs,
      85             :                      struct ntvfs_request *req, union smb_fsinfo *fs)
      86             : {
      87           0 :         NTSTATUS status;
      88        4195 :         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
      89             :                                   struct pvfs_state);
      90           0 :         uint64_t blocks_free, blocks_total;
      91           0 :         unsigned int bpunit;
      92           0 :         struct stat st;
      93        4195 :         const uint16_t block_size = 512;
      94             : 
      95             :         /* only some levels need the expensive sys_fsusage() call */
      96        4195 :         switch (fs->generic.level) {
      97          59 :         case RAW_QFS_DSKATTR:
      98             :         case RAW_QFS_ALLOCATION:
      99             :         case RAW_QFS_SIZE_INFO:
     100             :         case RAW_QFS_SIZE_INFORMATION:
     101             :         case RAW_QFS_FULL_SIZE_INFORMATION:
     102          59 :                 if (sys_fsusage(pvfs->base_directory, &blocks_free, &blocks_total) == -1) {
     103           0 :                         return pvfs_map_errno(pvfs, errno);
     104             :                 }
     105          59 :                 break;
     106        4136 :         default:
     107        4136 :                 break;
     108             :         }
     109             : 
     110        4195 :         if (stat(pvfs->base_directory, &st) != 0) {
     111           0 :                 return NT_STATUS_DISK_CORRUPT_ERROR;
     112             :         }
     113             : 
     114             :         /* now fill in the out fields */
     115        4195 :         switch (fs->generic.level) {
     116           0 :         case RAW_QFS_GENERIC:
     117         222 :                 return NT_STATUS_INVALID_LEVEL;
     118             : 
     119           1 :         case RAW_QFS_DSKATTR:
     120             :                 /* we need to scale the sizes to fit */
     121           6 :                 for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
     122           6 :                         if (blocks_total * (double)block_size < bpunit * 512 * 65535.0) {
     123           1 :                                 break;
     124             :                         }
     125             :                 }
     126           1 :                 fs->dskattr.out.blocks_per_unit = bpunit;
     127           1 :                 fs->dskattr.out.block_size = block_size;
     128           1 :                 fs->dskattr.out.units_total = (blocks_total * (double)block_size) / (bpunit * 512);
     129           1 :                 fs->dskattr.out.units_free  = (blocks_free  * (double)block_size) / (bpunit * 512);
     130             : 
     131             :                 /* we must return a maximum of 2G to old DOS systems, or they get very confused */
     132           1 :                 if (bpunit > 64 && req->ctx->protocol <= PROTOCOL_LANMAN2) {
     133           0 :                         fs->dskattr.out.blocks_per_unit = 64;
     134           0 :                         fs->dskattr.out.units_total = 0xFFFF;
     135           0 :                         fs->dskattr.out.units_free = 0xFFFF;
     136             :                 }
     137           1 :                 return NT_STATUS_OK;
     138             : 
     139           5 :         case RAW_QFS_ALLOCATION:
     140           5 :                 fs->allocation.out.fs_id = st.st_dev;
     141           5 :                 fs->allocation.out.total_alloc_units = blocks_total;
     142           5 :                 fs->allocation.out.avail_alloc_units = blocks_free;
     143           5 :                 fs->allocation.out.sectors_per_unit = 1;
     144           5 :                 fs->allocation.out.bytes_per_sector = block_size;
     145           5 :                 return NT_STATUS_OK;
     146             : 
     147           5 :         case RAW_QFS_VOLUME:
     148           5 :                 fs->volume.out.serial_number = st.st_ino;
     149           5 :                 fs->volume.out.volume_name.s = pvfs->share_name;
     150           5 :                 return NT_STATUS_OK;
     151             : 
     152          37 :         case RAW_QFS_VOLUME_INFO:
     153             :         case RAW_QFS_VOLUME_INFORMATION:
     154          37 :                 unix_to_nt_time(&fs->volume_info.out.create_time, st.st_ctime);
     155          37 :                 fs->volume_info.out.serial_number = st.st_ino;
     156          37 :                 fs->volume_info.out.volume_name.s = pvfs->share_name;
     157          37 :                 return NT_STATUS_OK;
     158             : 
     159          47 :         case RAW_QFS_SIZE_INFO:
     160             :         case RAW_QFS_SIZE_INFORMATION:
     161          47 :                 fs->size_info.out.total_alloc_units = blocks_total;
     162          47 :                 fs->size_info.out.avail_alloc_units = blocks_free;
     163          47 :                 fs->size_info.out.sectors_per_unit = 1;
     164          47 :                 fs->size_info.out.bytes_per_sector = block_size;
     165          47 :                 return NT_STATUS_OK;
     166             : 
     167          21 :         case RAW_QFS_DEVICE_INFO:
     168             :         case RAW_QFS_DEVICE_INFORMATION:
     169          21 :                 fs->device_info.out.device_type = 0;
     170          21 :                 fs->device_info.out.characteristics = 0;
     171          21 :                 return NT_STATUS_OK;
     172             : 
     173          75 :         case RAW_QFS_ATTRIBUTE_INFO:
     174             :         case RAW_QFS_ATTRIBUTE_INFORMATION:
     175          75 :                 fs->attribute_info.out.fs_attr                   = pvfs->fs_attribs;
     176          75 :                 fs->attribute_info.out.max_file_component_length = 255;
     177          75 :                 fs->attribute_info.out.fs_type.s                 = ntvfs->ctx->fs_type;
     178          75 :                 return NT_STATUS_OK;
     179             : 
     180           6 :         case RAW_QFS_QUOTA_INFORMATION:
     181           6 :                 ZERO_STRUCT(fs->quota_information.out.unknown);
     182           6 :                 fs->quota_information.out.quota_soft = 0;
     183           6 :                 fs->quota_information.out.quota_hard = 0;
     184           6 :                 fs->quota_information.out.quota_flags = 0;
     185           6 :                 return NT_STATUS_OK;
     186             : 
     187           6 :         case RAW_QFS_FULL_SIZE_INFORMATION:
     188           6 :                 fs->full_size_information.out.total_alloc_units = blocks_total;
     189           6 :                 fs->full_size_information.out.call_avail_alloc_units = blocks_free;
     190           6 :                 fs->full_size_information.out.actual_avail_alloc_units = blocks_free;
     191           6 :                 fs->full_size_information.out.sectors_per_unit = 1;
     192           6 :                 fs->full_size_information.out.bytes_per_sector = block_size;
     193           6 :                 return NT_STATUS_OK;
     194             : 
     195          15 :         case RAW_QFS_OBJECTID_INFORMATION:
     196          15 :                 ZERO_STRUCT(fs->objectid_information.out.guid);
     197          15 :                 ZERO_STRUCT(fs->objectid_information.out.unknown);
     198             : 
     199          15 :                 status = pvfs_cache_base_fs_uuid(pvfs, &st);
     200          15 :                 NT_STATUS_NOT_OK_RETURN(status);
     201             : 
     202          15 :                 fs->objectid_information.out.guid = *pvfs->base_fs_uuid;
     203          15 :                 return NT_STATUS_OK;
     204             : 
     205           4 :         case RAW_QFS_SECTOR_SIZE_INFORMATION:
     206           4 :                 fs->sector_size_info.out.logical_bytes_per_sector = block_size;
     207           0 :                 fs->sector_size_info.out.phys_bytes_per_sector_atomic
     208           4 :                                                                 = block_size;
     209           0 :                 fs->sector_size_info.out.phys_bytes_per_sector_perf
     210           4 :                                                                 = block_size;
     211           0 :                 fs->sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic
     212           4 :                                                                 = block_size;
     213           0 :                 fs->sector_size_info.out.flags
     214           4 :                                         = QFS_SSINFO_FLAGS_ALIGNED_DEVICE
     215             :                                 | QFS_SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE;
     216           4 :                 fs->sector_size_info.out.byte_off_sector_align = 0;
     217           4 :                 fs->sector_size_info.out.byte_off_partition_align = 0;
     218           4 :                 return NT_STATUS_OK;
     219             : 
     220        3973 :         default:
     221        3973 :                 break;
     222             :         }
     223        3973 :         return NT_STATUS_INVALID_LEVEL;
     224             : }

Generated by: LCOV version 1.14