github.com/tompao/docker@v1.9.1/pkg/devicemapper/devmapper_wrapper.go (about) 1 // +build linux 2 3 package devicemapper 4 5 /* 6 #cgo LDFLAGS: -L. -ldevmapper 7 #include <libdevmapper.h> 8 #include <linux/loop.h> // FIXME: present only for defines, maybe we can remove it? 9 #include <linux/fs.h> // FIXME: present only for BLKGETSIZE64, maybe we can remove it? 10 11 #ifndef LOOP_CTL_GET_FREE 12 #define LOOP_CTL_GET_FREE 0x4C82 13 #endif 14 15 #ifndef LO_FLAGS_PARTSCAN 16 #define LO_FLAGS_PARTSCAN 8 17 #endif 18 19 // FIXME: Can't we find a way to do the logging in pure Go? 20 extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str); 21 22 static void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...) 23 { 24 char buffer[256]; 25 va_list ap; 26 27 va_start(ap, f); 28 vsnprintf(buffer, 256, f, ap); 29 va_end(ap); 30 31 DevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer); 32 } 33 34 static void log_with_errno_init() 35 { 36 dm_log_with_errno_init(log_cb); 37 } 38 */ 39 import "C" 40 41 import ( 42 "reflect" 43 "unsafe" 44 ) 45 46 type ( 47 cdmTask C.struct_dm_task 48 49 cLoopInfo64 C.struct_loop_info64 50 loopInfo64 struct { 51 loDevice uint64 /* ioctl r/o */ 52 loInode uint64 /* ioctl r/o */ 53 loRdevice uint64 /* ioctl r/o */ 54 loOffset uint64 55 loSizelimit uint64 /* bytes, 0 == max available */ 56 loNumber uint32 /* ioctl r/o */ 57 loEncryptType uint32 58 loEncryptKeySize uint32 /* ioctl w/o */ 59 loFlags uint32 /* ioctl r/o */ 60 loFileName [LoNameSize]uint8 61 loCryptName [LoNameSize]uint8 62 loEncryptKey [LoKeySize]uint8 /* ioctl w/o */ 63 loInit [2]uint64 64 } 65 ) 66 67 // IOCTL consts 68 const ( 69 BlkGetSize64 = C.BLKGETSIZE64 70 BlkDiscard = C.BLKDISCARD 71 72 LoopSetFd = C.LOOP_SET_FD 73 LoopCtlGetFree = C.LOOP_CTL_GET_FREE 74 LoopGetStatus64 = C.LOOP_GET_STATUS64 75 LoopSetStatus64 = C.LOOP_SET_STATUS64 76 LoopClrFd = C.LOOP_CLR_FD 77 LoopSetCapacity = C.LOOP_SET_CAPACITY 78 ) 79 80 // LOOP consts. 81 const ( 82 LoFlagsAutoClear = C.LO_FLAGS_AUTOCLEAR 83 LoFlagsReadOnly = C.LO_FLAGS_READ_ONLY 84 LoFlagsPartScan = C.LO_FLAGS_PARTSCAN 85 LoKeySize = C.LO_KEY_SIZE 86 LoNameSize = C.LO_NAME_SIZE 87 ) 88 89 // Devicemapper cookie flags. 90 const ( 91 DmUdevDisableSubsystemRulesFlag = C.DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 92 DmUdevDisableDiskRulesFlag = C.DM_UDEV_DISABLE_DISK_RULES_FLAG 93 DmUdevDisableOtherRulesFlag = C.DM_UDEV_DISABLE_OTHER_RULES_FLAG 94 DmUdevDisableLibraryFallback = C.DM_UDEV_DISABLE_LIBRARY_FALLBACK 95 ) 96 97 // DeviceMapper mapped functions. 98 var ( 99 DmGetLibraryVersion = dmGetLibraryVersionFct 100 DmGetNextTarget = dmGetNextTargetFct 101 DmLogInitVerbose = dmLogInitVerboseFct 102 DmSetDevDir = dmSetDevDirFct 103 DmTaskAddTarget = dmTaskAddTargetFct 104 DmTaskCreate = dmTaskCreateFct 105 DmTaskDestroy = dmTaskDestroyFct 106 DmTaskGetDeps = dmTaskGetDepsFct 107 DmTaskGetInfo = dmTaskGetInfoFct 108 DmTaskGetDriverVersion = dmTaskGetDriverVersionFct 109 DmTaskRun = dmTaskRunFct 110 DmTaskSetAddNode = dmTaskSetAddNodeFct 111 DmTaskSetCookie = dmTaskSetCookieFct 112 DmTaskSetMessage = dmTaskSetMessageFct 113 DmTaskSetName = dmTaskSetNameFct 114 DmTaskSetRo = dmTaskSetRoFct 115 DmTaskSetSector = dmTaskSetSectorFct 116 DmUdevWait = dmUdevWaitFct 117 DmUdevSetSyncSupport = dmUdevSetSyncSupportFct 118 DmUdevGetSyncSupport = dmUdevGetSyncSupportFct 119 DmCookieSupported = dmCookieSupportedFct 120 LogWithErrnoInit = logWithErrnoInitFct 121 DmTaskDeferredRemove = dmTaskDeferredRemoveFct 122 DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct 123 ) 124 125 func free(p *C.char) { 126 C.free(unsafe.Pointer(p)) 127 } 128 129 func dmTaskDestroyFct(task *cdmTask) { 130 C.dm_task_destroy((*C.struct_dm_task)(task)) 131 } 132 133 func dmTaskCreateFct(taskType int) *cdmTask { 134 return (*cdmTask)(C.dm_task_create(C.int(taskType))) 135 } 136 137 func dmTaskRunFct(task *cdmTask) int { 138 ret, _ := C.dm_task_run((*C.struct_dm_task)(task)) 139 return int(ret) 140 } 141 142 func dmTaskSetNameFct(task *cdmTask, name string) int { 143 Cname := C.CString(name) 144 defer free(Cname) 145 146 return int(C.dm_task_set_name((*C.struct_dm_task)(task), Cname)) 147 } 148 149 func dmTaskSetMessageFct(task *cdmTask, message string) int { 150 Cmessage := C.CString(message) 151 defer free(Cmessage) 152 153 return int(C.dm_task_set_message((*C.struct_dm_task)(task), Cmessage)) 154 } 155 156 func dmTaskSetSectorFct(task *cdmTask, sector uint64) int { 157 return int(C.dm_task_set_sector((*C.struct_dm_task)(task), C.uint64_t(sector))) 158 } 159 160 func dmTaskSetCookieFct(task *cdmTask, cookie *uint, flags uint16) int { 161 cCookie := C.uint32_t(*cookie) 162 defer func() { 163 *cookie = uint(cCookie) 164 }() 165 return int(C.dm_task_set_cookie((*C.struct_dm_task)(task), &cCookie, C.uint16_t(flags))) 166 } 167 168 func dmTaskSetAddNodeFct(task *cdmTask, addNode AddNodeType) int { 169 return int(C.dm_task_set_add_node((*C.struct_dm_task)(task), C.dm_add_node_t(addNode))) 170 } 171 172 func dmTaskSetRoFct(task *cdmTask) int { 173 return int(C.dm_task_set_ro((*C.struct_dm_task)(task))) 174 } 175 176 func dmTaskAddTargetFct(task *cdmTask, 177 start, size uint64, ttype, params string) int { 178 179 Cttype := C.CString(ttype) 180 defer free(Cttype) 181 182 Cparams := C.CString(params) 183 defer free(Cparams) 184 185 return int(C.dm_task_add_target((*C.struct_dm_task)(task), C.uint64_t(start), C.uint64_t(size), Cttype, Cparams)) 186 } 187 188 func dmTaskGetDepsFct(task *cdmTask) *Deps { 189 Cdeps := C.dm_task_get_deps((*C.struct_dm_task)(task)) 190 if Cdeps == nil { 191 return nil 192 } 193 194 // golang issue: https://github.com/golang/go/issues/11925 195 hdr := reflect.SliceHeader{ 196 Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))), 197 Len: int(Cdeps.count), 198 Cap: int(Cdeps.count), 199 } 200 devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr)) 201 202 deps := &Deps{ 203 Count: uint32(Cdeps.count), 204 Filler: uint32(Cdeps.filler), 205 } 206 for _, device := range devices { 207 deps.Device = append(deps.Device, uint64(device)) 208 } 209 return deps 210 } 211 212 func dmTaskGetInfoFct(task *cdmTask, info *Info) int { 213 Cinfo := C.struct_dm_info{} 214 defer func() { 215 info.Exists = int(Cinfo.exists) 216 info.Suspended = int(Cinfo.suspended) 217 info.LiveTable = int(Cinfo.live_table) 218 info.InactiveTable = int(Cinfo.inactive_table) 219 info.OpenCount = int32(Cinfo.open_count) 220 info.EventNr = uint32(Cinfo.event_nr) 221 info.Major = uint32(Cinfo.major) 222 info.Minor = uint32(Cinfo.minor) 223 info.ReadOnly = int(Cinfo.read_only) 224 info.TargetCount = int32(Cinfo.target_count) 225 }() 226 return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) 227 } 228 229 func dmTaskGetDriverVersionFct(task *cdmTask) string { 230 buffer := C.malloc(128) 231 defer C.free(buffer) 232 res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128) 233 if res == 0 { 234 return "" 235 } 236 return C.GoString((*C.char)(buffer)) 237 } 238 239 func dmGetNextTargetFct(task *cdmTask, next unsafe.Pointer, start, length *uint64, target, params *string) unsafe.Pointer { 240 var ( 241 Cstart, Clength C.uint64_t 242 CtargetType, Cparams *C.char 243 ) 244 defer func() { 245 *start = uint64(Cstart) 246 *length = uint64(Clength) 247 *target = C.GoString(CtargetType) 248 *params = C.GoString(Cparams) 249 }() 250 251 nextp := C.dm_get_next_target((*C.struct_dm_task)(task), next, &Cstart, &Clength, &CtargetType, &Cparams) 252 return nextp 253 } 254 255 func dmUdevSetSyncSupportFct(syncWithUdev int) { 256 (C.dm_udev_set_sync_support(C.int(syncWithUdev))) 257 } 258 259 func dmUdevGetSyncSupportFct() int { 260 return int(C.dm_udev_get_sync_support()) 261 } 262 263 func dmUdevWaitFct(cookie uint) int { 264 return int(C.dm_udev_wait(C.uint32_t(cookie))) 265 } 266 267 func dmCookieSupportedFct() int { 268 return int(C.dm_cookie_supported()) 269 } 270 271 func dmLogInitVerboseFct(level int) { 272 C.dm_log_init_verbose(C.int(level)) 273 } 274 275 func logWithErrnoInitFct() { 276 C.log_with_errno_init() 277 } 278 279 func dmSetDevDirFct(dir string) int { 280 Cdir := C.CString(dir) 281 defer free(Cdir) 282 283 return int(C.dm_set_dev_dir(Cdir)) 284 } 285 286 func dmGetLibraryVersionFct(version *string) int { 287 buffer := C.CString(string(make([]byte, 128))) 288 defer free(buffer) 289 defer func() { 290 *version = C.GoString(buffer) 291 }() 292 return int(C.dm_get_library_version(buffer, 128)) 293 }