github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/pkg/devicemapper/devmapper_wrapper.go (about) 1 //go:build linux && cgo 2 // +build linux,cgo 3 4 package devicemapper // import "github.com/docker/docker/pkg/devicemapper" 5 6 /* 7 #define _GNU_SOURCE 8 #include <libdevmapper.h> 9 #include <linux/fs.h> // FIXME: present only for BLKGETSIZE64, maybe we can remove it? 10 11 // FIXME: Can't we find a way to do the logging in pure Go? 12 extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str); 13 14 static void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...) 15 { 16 char *buffer = NULL; 17 va_list ap; 18 int ret; 19 20 va_start(ap, f); 21 ret = vasprintf(&buffer, f, ap); 22 va_end(ap); 23 if (ret < 0) { 24 // memory allocation failed -- should never happen? 25 return; 26 } 27 28 DevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer); 29 free(buffer); 30 } 31 32 static void log_with_errno_init() 33 { 34 dm_log_with_errno_init(log_cb); 35 } 36 */ 37 import "C" 38 39 import ( 40 "reflect" 41 "unsafe" 42 ) 43 44 type ( 45 cdmTask C.struct_dm_task 46 ) 47 48 // IOCTL consts 49 const ( 50 BlkGetSize64 = C.BLKGETSIZE64 51 BlkDiscard = C.BLKDISCARD 52 ) 53 54 // Devicemapper cookie flags. 55 const ( 56 DmUdevDisableSubsystemRulesFlag = C.DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 57 DmUdevDisableDiskRulesFlag = C.DM_UDEV_DISABLE_DISK_RULES_FLAG 58 DmUdevDisableOtherRulesFlag = C.DM_UDEV_DISABLE_OTHER_RULES_FLAG 59 DmUdevDisableLibraryFallback = C.DM_UDEV_DISABLE_LIBRARY_FALLBACK 60 ) 61 62 // DeviceMapper mapped functions. 63 var ( 64 DmGetLibraryVersion = dmGetLibraryVersionFct 65 DmGetNextTarget = dmGetNextTargetFct 66 DmSetDevDir = dmSetDevDirFct 67 DmTaskAddTarget = dmTaskAddTargetFct 68 DmTaskCreate = dmTaskCreateFct 69 DmTaskDestroy = dmTaskDestroyFct 70 DmTaskGetDeps = dmTaskGetDepsFct 71 DmTaskGetInfo = dmTaskGetInfoFct 72 DmTaskGetDriverVersion = dmTaskGetDriverVersionFct 73 DmTaskRun = dmTaskRunFct 74 DmTaskSetAddNode = dmTaskSetAddNodeFct 75 DmTaskSetCookie = dmTaskSetCookieFct 76 DmTaskSetMessage = dmTaskSetMessageFct 77 DmTaskSetName = dmTaskSetNameFct 78 DmTaskSetSector = dmTaskSetSectorFct 79 DmUdevWait = dmUdevWaitFct 80 DmUdevSetSyncSupport = dmUdevSetSyncSupportFct 81 DmUdevGetSyncSupport = dmUdevGetSyncSupportFct 82 DmCookieSupported = dmCookieSupportedFct 83 LogWithErrnoInit = logWithErrnoInitFct 84 DmTaskDeferredRemove = dmTaskDeferredRemoveFct 85 DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct 86 ) 87 88 func free(p *C.char) { 89 C.free(unsafe.Pointer(p)) 90 } 91 92 func dmTaskDestroyFct(task *cdmTask) { 93 C.dm_task_destroy((*C.struct_dm_task)(task)) 94 } 95 96 func dmTaskCreateFct(taskType int) *cdmTask { 97 return (*cdmTask)(C.dm_task_create(C.int(taskType))) 98 } 99 100 func dmTaskRunFct(task *cdmTask) int { 101 ret, _ := C.dm_task_run((*C.struct_dm_task)(task)) 102 return int(ret) 103 } 104 105 func dmTaskSetNameFct(task *cdmTask, name string) int { 106 Cname := C.CString(name) 107 defer free(Cname) 108 109 return int(C.dm_task_set_name((*C.struct_dm_task)(task), Cname)) 110 } 111 112 func dmTaskSetMessageFct(task *cdmTask, message string) int { 113 Cmessage := C.CString(message) 114 defer free(Cmessage) 115 116 return int(C.dm_task_set_message((*C.struct_dm_task)(task), Cmessage)) 117 } 118 119 func dmTaskSetSectorFct(task *cdmTask, sector uint64) int { 120 return int(C.dm_task_set_sector((*C.struct_dm_task)(task), C.uint64_t(sector))) 121 } 122 123 func dmTaskSetCookieFct(task *cdmTask, cookie *uint, flags uint16) int { 124 cCookie := C.uint32_t(*cookie) 125 defer func() { 126 *cookie = uint(cCookie) 127 }() 128 return int(C.dm_task_set_cookie((*C.struct_dm_task)(task), &cCookie, C.uint16_t(flags))) 129 } 130 131 func dmTaskSetAddNodeFct(task *cdmTask, addNode AddNodeType) int { 132 return int(C.dm_task_set_add_node((*C.struct_dm_task)(task), C.dm_add_node_t(addNode))) 133 } 134 135 func dmTaskAddTargetFct(task *cdmTask, 136 start, size uint64, ttype, params string) int { 137 138 Cttype := C.CString(ttype) 139 defer free(Cttype) 140 141 Cparams := C.CString(params) 142 defer free(Cparams) 143 144 return int(C.dm_task_add_target((*C.struct_dm_task)(task), C.uint64_t(start), C.uint64_t(size), Cttype, Cparams)) 145 } 146 147 func dmTaskGetDepsFct(task *cdmTask) *Deps { 148 Cdeps := C.dm_task_get_deps((*C.struct_dm_task)(task)) 149 if Cdeps == nil { 150 return nil 151 } 152 153 // golang issue: https://github.com/golang/go/issues/11925 154 var devices []C.uint64_t 155 devicesHdr := (*reflect.SliceHeader)(unsafe.Pointer(&devices)) 156 devicesHdr.Data = uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))) 157 devicesHdr.Len = int(Cdeps.count) 158 devicesHdr.Cap = int(Cdeps.count) 159 160 deps := &Deps{ 161 Count: uint32(Cdeps.count), 162 Filler: uint32(Cdeps.filler), 163 } 164 for _, device := range devices { 165 deps.Device = append(deps.Device, uint64(device)) 166 } 167 return deps 168 } 169 170 func dmTaskGetInfoFct(task *cdmTask, info *Info) int { 171 Cinfo := C.struct_dm_info{} 172 defer func() { 173 info.Exists = int(Cinfo.exists) 174 info.Suspended = int(Cinfo.suspended) 175 info.LiveTable = int(Cinfo.live_table) 176 info.InactiveTable = int(Cinfo.inactive_table) 177 info.OpenCount = int32(Cinfo.open_count) 178 info.EventNr = uint32(Cinfo.event_nr) 179 info.Major = uint32(Cinfo.major) 180 info.Minor = uint32(Cinfo.minor) 181 info.ReadOnly = int(Cinfo.read_only) 182 info.TargetCount = int32(Cinfo.target_count) 183 }() 184 return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) 185 } 186 187 func dmTaskGetDriverVersionFct(task *cdmTask) string { 188 buffer := C.malloc(128) 189 defer C.free(buffer) 190 res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128) 191 if res == 0 { 192 return "" 193 } 194 return C.GoString((*C.char)(buffer)) 195 } 196 197 func dmGetNextTargetFct(task *cdmTask, next unsafe.Pointer, start, length *uint64, target, params *string) unsafe.Pointer { 198 var ( 199 Cstart, Clength C.uint64_t 200 CtargetType, Cparams *C.char 201 ) 202 defer func() { 203 *start = uint64(Cstart) 204 *length = uint64(Clength) 205 *target = C.GoString(CtargetType) 206 *params = C.GoString(Cparams) 207 }() 208 209 //lint:ignore SA4000 false positive on (identical expressions on the left and right side of the '==' operator) (staticcheck) 210 nextp := C.dm_get_next_target((*C.struct_dm_task)(task), next, &Cstart, &Clength, &CtargetType, &Cparams) 211 return nextp 212 } 213 214 func dmUdevSetSyncSupportFct(syncWithUdev int) { 215 C.dm_udev_set_sync_support(C.int(syncWithUdev)) 216 } 217 218 func dmUdevGetSyncSupportFct() int { 219 return int(C.dm_udev_get_sync_support()) 220 } 221 222 func dmUdevWaitFct(cookie uint) int { 223 return int(C.dm_udev_wait(C.uint32_t(cookie))) 224 } 225 226 func dmCookieSupportedFct() int { 227 return int(C.dm_cookie_supported()) 228 } 229 230 func logWithErrnoInitFct() { 231 C.log_with_errno_init() 232 } 233 234 func dmSetDevDirFct(dir string) int { 235 Cdir := C.CString(dir) 236 defer free(Cdir) 237 238 return int(C.dm_set_dev_dir(Cdir)) 239 } 240 241 func dmGetLibraryVersionFct(version *string) int { 242 buffer := C.CString(string(make([]byte, 128))) 243 defer free(buffer) 244 defer func() { 245 *version = C.GoString(buffer) 246 }() 247 return int(C.dm_get_library_version(buffer, 128)) 248 }