View Javadoc
1   /*
2    * Copyright 2016-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.util.platform.unix.freebsd;
6   
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import com.sun.jna.Memory;
11  import com.sun.jna.Native;
12  import com.sun.jna.Structure;
13  import com.sun.jna.platform.unix.LibCAPI.size_t;
14  
15  import oshi.annotation.concurrent.ThreadSafe;
16  import oshi.jna.ByRef.CloseableSizeTByReference;
17  import oshi.jna.platform.unix.FreeBsdLibc;
18  
19  /**
20   * Provides access to sysctl calls on FreeBSD
21   */
22  @ThreadSafe
23  public final class BsdSysctlUtil {
24  
25      private static final Logger LOG = LoggerFactory.getLogger(BsdSysctlUtil.class);
26  
27      private static final String SYSCTL_FAIL = "Failed sysctl call: {}, Error code: {}";
28  
29      private BsdSysctlUtil() {
30      }
31  
32      /**
33       * Executes a sysctl call with an int result
34       *
35       * @param name name of the sysctl
36       * @param def  default int value
37       * @return The int result of the call if successful; the default otherwise
38       */
39      public static int sysctl(String name, int def) {
40          int intSize = FreeBsdLibc.INT_SIZE;
41          try (Memory p = new Memory(intSize); CloseableSizeTByReference size = new CloseableSizeTByReference(intSize)) {
42              if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, p, size, null, size_t.ZERO)) {
43                  LOG.warn(SYSCTL_FAIL, name, Native.getLastError());
44                  return def;
45              }
46              return p.getInt(0);
47          }
48      }
49  
50      /**
51       * Executes a sysctl call with a long result
52       *
53       * @param name name of the sysctl
54       * @param def  default long value
55       * @return The long result of the call if successful; the default otherwise
56       */
57      public static long sysctl(String name, long def) {
58          int uint64Size = FreeBsdLibc.UINT64_SIZE;
59          try (Memory p = new Memory(uint64Size);
60                  CloseableSizeTByReference size = new CloseableSizeTByReference(uint64Size)) {
61              if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, p, size, null, size_t.ZERO)) {
62                  LOG.warn(SYSCTL_FAIL, name, Native.getLastError());
63                  return def;
64              }
65              return p.getLong(0);
66          }
67      }
68  
69      /**
70       * Executes a sysctl call with a String result
71       *
72       * @param name name of the sysctl
73       * @param def  default String value
74       * @return The String result of the call if successful; the default otherwise
75       */
76      public static String sysctl(String name, String def) {
77          // Call first time with null pointer to get value of size
78          try (CloseableSizeTByReference size = new CloseableSizeTByReference()) {
79              if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, null, size, null, size_t.ZERO)) {
80                  LOG.warn(SYSCTL_FAIL, name, Native.getLastError());
81                  return def;
82              }
83              // Add 1 to size for null terminated string
84              try (Memory p = new Memory(size.longValue() + 1L)) {
85                  if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, p, size, null, size_t.ZERO)) {
86                      LOG.warn(SYSCTL_FAIL, name, Native.getLastError());
87                      return def;
88                  }
89                  return p.getString(0);
90              }
91          }
92      }
93  
94      /**
95       * Executes a sysctl call with a Structure result
96       *
97       * @param name   name of the sysctl
98       * @param struct structure for the result
99       * @return True if structure is successfuly populated, false otherwise
100      */
101     public static boolean sysctl(String name, Structure struct) {
102         try (CloseableSizeTByReference size = new CloseableSizeTByReference(struct.size())) {
103             if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, struct.getPointer(), size, null, size_t.ZERO)) {
104                 LOG.error(SYSCTL_FAIL, name, Native.getLastError());
105                 return false;
106             }
107         }
108         struct.read();
109         return true;
110     }
111 
112     /**
113      * Executes a sysctl call with a Pointer result
114      *
115      * @param name name of the sysctl
116      * @return An allocated memory buffer containing the result on success, null otherwise. Its value on failure is
117      *         undefined.
118      */
119     public static Memory sysctl(String name) {
120         try (CloseableSizeTByReference size = new CloseableSizeTByReference()) {
121             if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, null, size, null, size_t.ZERO)) {
122                 LOG.error(SYSCTL_FAIL, name, Native.getLastError());
123                 return null;
124             }
125             Memory m = new Memory(size.longValue());
126             if (0 != FreeBsdLibc.INSTANCE.sysctlbyname(name, m, size, null, size_t.ZERO)) {
127                 LOG.error(SYSCTL_FAIL, name, Native.getLastError());
128                 m.close();
129                 return null;
130             }
131             return m;
132         }
133     }
134 }