github.com/rsampaio/docker@v0.7.2-0.20150827203920-fdc73cc3fc31/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 loEncrypt_type uint32 58 loEncrypt_key_size 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 const ( 81 LoFlagsAutoClear = C.LO_FLAGS_AUTOCLEAR 82 LoFlagsReadOnly = C.LO_FLAGS_READ_ONLY 83 LoFlagsPartScan = C.LO_FLAGS_PARTSCAN 84 LoKeySize = C.LO_KEY_SIZE 85 LoNameSize = C.LO_NAME_SIZE 86 ) 87 88 const ( 89 DmUdevDisableSubsystemRulesFlag = C.DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 90 DmUdevDisableDiskRulesFlag = C.DM_UDEV_DISABLE_DISK_RULES_FLAG 91 DmUdevDisableOtherRulesFlag = C.DM_UDEV_DISABLE_OTHER_RULES_FLAG 92 DmUdevDisableLibraryFallback = C.DM_UDEV_DISABLE_LIBRARY_FALLBACK 93 ) 94 95 var ( 96 DmGetLibraryVersion = dmGetLibraryVersionFct 97 DmGetNextTarget = dmGetNextTargetFct 98 DmLogInitVerbose = dmLogInitVerboseFct 99 DmSetDevDir = dmSetDevDirFct 100 DmTaskAddTarget = dmTaskAddTargetFct 101 DmTaskCreate = dmTaskCreateFct 102 DmTaskDestroy = dmTaskDestroyFct 103 DmTaskGetDeps = dmTaskGetDepsFct 104 DmTaskGetInfo = dmTaskGetInfoFct 105 DmTaskGetDriverVersion = dmTaskGetDriverVersionFct 106 DmTaskRun = dmTaskRunFct 107 DmTaskSetAddNode = dmTaskSetAddNodeFct 108 DmTaskSetCookie = dmTaskSetCookieFct 109 DmTaskSetMessage = dmTaskSetMessageFct 110 DmTaskSetName = dmTaskSetNameFct 111 DmTaskSetRo = dmTaskSetRoFct 112 DmTaskSetSector = dmTaskSetSectorFct 113 DmUdevWait = dmUdevWaitFct 114 DmUdevSetSyncSupport = dmUdevSetSyncSupportFct 115 DmUdevGetSyncSupport = dmUdevGetSyncSupportFct 116 DmCookieSupported = dmCookieSupportedFct 117 LogWithErrnoInit = logWithErrnoInitFct 118 DmTaskDeferredRemove = dmTaskDeferredRemoveFct 119 DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct 120 ) 121 122 func free(p *C.char) { 123 C.free(unsafe.Pointer(p)) 124 } 125 126 func dmTaskDestroyFct(task *CDmTask) { 127 C.dm_task_destroy((*C.struct_dm_task)(task)) 128 } 129 130 func dmTaskCreateFct(taskType int) *CDmTask { 131 return (*CDmTask)(C.dm_task_create(C.int(taskType))) 132 } 133 134 func dmTaskRunFct(task *CDmTask) int { 135 ret, _ := C.dm_task_run((*C.struct_dm_task)(task)) 136 return int(ret) 137 } 138 139 func dmTaskSetNameFct(task *CDmTask, name string) int { 140 Cname := C.CString(name) 141 defer free(Cname) 142 143 return int(C.dm_task_set_name((*C.struct_dm_task)(task), Cname)) 144 } 145 146 func dmTaskSetMessageFct(task *CDmTask, message string) int { 147 Cmessage := C.CString(message) 148 defer free(Cmessage) 149 150 return int(C.dm_task_set_message((*C.struct_dm_task)(task), Cmessage)) 151 } 152 153 func dmTaskSetSectorFct(task *CDmTask, sector uint64) int { 154 return int(C.dm_task_set_sector((*C.struct_dm_task)(task), C.uint64_t(sector))) 155 } 156 157 func dmTaskSetCookieFct(task *CDmTask, cookie *uint, flags uint16) int { 158 cCookie := C.uint32_t(*cookie) 159 defer func() { 160 *cookie = uint(cCookie) 161 }() 162 return int(C.dm_task_set_cookie((*C.struct_dm_task)(task), &cCookie, C.uint16_t(flags))) 163 } 164 165 func dmTaskSetAddNodeFct(task *CDmTask, addNode AddNodeType) int { 166 return int(C.dm_task_set_add_node((*C.struct_dm_task)(task), C.dm_add_node_t(addNode))) 167 } 168 169 func dmTaskSetRoFct(task *CDmTask) int { 170 return int(C.dm_task_set_ro((*C.struct_dm_task)(task))) 171 } 172 173 func dmTaskAddTargetFct(task *CDmTask, 174 start, size uint64, ttype, params string) int { 175 176 Cttype := C.CString(ttype) 177 defer free(Cttype) 178 179 Cparams := C.CString(params) 180 defer free(Cparams) 181 182 return int(C.dm_task_add_target((*C.struct_dm_task)(task), C.uint64_t(start), C.uint64_t(size), Cttype, Cparams)) 183 } 184 185 func dmTaskGetDepsFct(task *CDmTask) *Deps { 186 Cdeps := C.dm_task_get_deps((*C.struct_dm_task)(task)) 187 if Cdeps == nil { 188 return nil 189 } 190 191 // golang issue: https://github.com/golang/go/issues/11925 192 hdr := reflect.SliceHeader{ 193 Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))), 194 Len: int(Cdeps.count), 195 Cap: int(Cdeps.count), 196 } 197 devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr)) 198 199 deps := &Deps{ 200 Count: uint32(Cdeps.count), 201 Filler: uint32(Cdeps.filler), 202 } 203 for _, device := range devices { 204 deps.Device = append(deps.Device, uint64(device)) 205 } 206 return deps 207 } 208 209 func dmTaskGetInfoFct(task *CDmTask, info *Info) int { 210 Cinfo := C.struct_dm_info{} 211 defer func() { 212 info.Exists = int(Cinfo.exists) 213 info.Suspended = int(Cinfo.suspended) 214 info.LiveTable = int(Cinfo.live_table) 215 info.InactiveTable = int(Cinfo.inactive_table) 216 info.OpenCount = int32(Cinfo.open_count) 217 info.EventNr = uint32(Cinfo.event_nr) 218 info.Major = uint32(Cinfo.major) 219 info.Minor = uint32(Cinfo.minor) 220 info.ReadOnly = int(Cinfo.read_only) 221 info.TargetCount = int32(Cinfo.target_count) 222 }() 223 return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) 224 } 225 226 func dmTaskGetDriverVersionFct(task *CDmTask) string { 227 buffer := C.malloc(128) 228 defer C.free(buffer) 229 res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128) 230 if res == 0 { 231 return "" 232 } 233 return C.GoString((*C.char)(buffer)) 234 } 235 236 func dmGetNextTargetFct(task *CDmTask, next unsafe.Pointer, start, length *uint64, target, params *string) unsafe.Pointer { 237 var ( 238 Cstart, Clength C.uint64_t 239 CtargetType, Cparams *C.char 240 ) 241 defer func() { 242 *start = uint64(Cstart) 243 *length = uint64(Clength) 244 *target = C.GoString(CtargetType) 245 *params = C.GoString(Cparams) 246 }() 247 248 nextp := C.dm_get_next_target((*C.struct_dm_task)(task), next, &Cstart, &Clength, &CtargetType, &Cparams) 249 return nextp 250 } 251 252 func dmUdevSetSyncSupportFct(syncWithUdev int) { 253 (C.dm_udev_set_sync_support(C.int(syncWithUdev))) 254 } 255 256 func dmUdevGetSyncSupportFct() int { 257 return int(C.dm_udev_get_sync_support()) 258 } 259 260 func dmUdevWaitFct(cookie uint) int { 261 return int(C.dm_udev_wait(C.uint32_t(cookie))) 262 } 263 264 func dmCookieSupportedFct() int { 265 return int(C.dm_cookie_supported()) 266 } 267 268 func dmLogInitVerboseFct(level int) { 269 C.dm_log_init_verbose(C.int(level)) 270 } 271 272 func logWithErrnoInitFct() { 273 C.log_with_errno_init() 274 } 275 276 func dmSetDevDirFct(dir string) int { 277 Cdir := C.CString(dir) 278 defer free(Cdir) 279 280 return int(C.dm_set_dev_dir(Cdir)) 281 } 282 283 func dmGetLibraryVersionFct(version *string) int { 284 buffer := C.CString(string(make([]byte, 128))) 285 defer free(buffer) 286 defer func() { 287 *version = C.GoString(buffer) 288 }() 289 return int(C.dm_get_library_version(buffer, 128)) 290 }