handle.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. // handle.go - libalpm handle type and methods.
  2. //
  3. // Copyright (c) 2013 The go-alpm Authors
  4. //
  5. // MIT Licensed. See LICENSE for details.
  6. // Package alpm implements Go bindings to the libalpm library used by Pacman,
  7. // the Arch Linux package manager. Libalpm allows the creation of custom front
  8. // ends to the Arch Linux package ecosystem.
  9. //
  10. // Libalpm does not include support for the Arch User Repository (AUR).
  11. package alpm
  12. // #include <alpm.h>
  13. // #include <stdio.h> //C.free
  14. // #include <fnmatch.h> //C.FNM_NOMATCH
  15. import "C"
  16. import (
  17. "unsafe"
  18. )
  19. // Handle contains the pointer to the alpm handle
  20. type Handle struct {
  21. ptr *C.alpm_handle_t
  22. }
  23. // Init initializes alpm handle
  24. func Init(root, dbpath string) (*Handle, error) {
  25. cRoot := C.CString(root)
  26. cDBPath := C.CString(dbpath)
  27. var cErr C.alpm_errno_t
  28. h := C.alpm_initialize(cRoot, cDBPath, &cErr)
  29. defer C.free(unsafe.Pointer(cRoot))
  30. defer C.free(unsafe.Pointer(cDBPath))
  31. if cErr != 0 {
  32. return nil, Error(cErr)
  33. }
  34. return &Handle{h}, nil
  35. }
  36. // Release releases the alpm handle
  37. func (h *Handle) Release() error {
  38. if er := C.alpm_release(h.ptr); er != 0 {
  39. return Error(er)
  40. }
  41. h.ptr = nil
  42. return nil
  43. }
  44. // LastError gets the last pm_error
  45. func (h Handle) LastError() error {
  46. if h.ptr != nil {
  47. cErr := C.alpm_errno(h.ptr)
  48. if cErr != 0 {
  49. return Error(cErr)
  50. }
  51. }
  52. return nil
  53. }
  54. //
  55. //alpm options getters and setters
  56. //
  57. //helper functions for wrapping list_t getters and setters
  58. func (h Handle) optionGetList(f func(*C.alpm_handle_t) *C.alpm_list_t) (StringList, error) {
  59. alpmList := f(h.ptr)
  60. goList := StringList{(*list)(unsafe.Pointer(alpmList))}
  61. if alpmList == nil {
  62. return goList, h.LastError()
  63. }
  64. return goList, nil
  65. }
  66. func (h Handle) optionSetList(hookDirs []string, f func(*C.alpm_handle_t, *C.alpm_list_t) C.int) error {
  67. var list *C.alpm_list_t
  68. for _, dir := range hookDirs {
  69. cDir := C.CString(dir)
  70. list = C.alpm_list_add(list, unsafe.Pointer(cDir))
  71. defer C.free(unsafe.Pointer(cDir))
  72. }
  73. ok := f(h.ptr, list)
  74. if ok < 0 {
  75. return h.LastError()
  76. }
  77. return nil
  78. }
  79. func (h Handle) optionAddList(hookDir string, f func(*C.alpm_handle_t, *C.char) C.int) error {
  80. cHookDir := C.CString(hookDir)
  81. defer C.free(unsafe.Pointer(cHookDir))
  82. ok := f(h.ptr, cHookDir)
  83. if ok < 0 {
  84. return h.LastError()
  85. }
  86. return nil
  87. }
  88. func (h Handle) optionRemoveList(dir string, f func(*C.alpm_handle_t, *C.char) C.int) (bool, error) {
  89. cDir := C.CString(dir)
  90. ok := f(h.ptr, cDir)
  91. defer C.free(unsafe.Pointer(cDir))
  92. if ok < 0 {
  93. return ok == 1, h.LastError()
  94. }
  95. return ok == 1, nil
  96. }
  97. func (h Handle) optionMatchList(dir string, f func(*C.alpm_handle_t, *C.char) C.int) (bool, error) {
  98. cDir := C.CString(dir)
  99. ok := f(h.ptr, cDir)
  100. defer C.free(unsafe.Pointer(cDir))
  101. if ok == 0 {
  102. return true, nil
  103. } else if ok == C.FNM_NOMATCH {
  104. return false, h.LastError()
  105. }
  106. return false, nil
  107. }
  108. //helper functions for *char based getters and setters
  109. func (h Handle) optionGetStr(f func(*C.alpm_handle_t) *C.char) (string, error) {
  110. cStr := f(h.ptr)
  111. str := C.GoString(cStr)
  112. if cStr == nil {
  113. return str, h.LastError()
  114. }
  115. return str, nil
  116. }
  117. func (h Handle) optionSetStr(str string, f func(*C.alpm_handle_t, *C.char) C.int) error {
  118. cStr := C.CString(str)
  119. defer C.free(unsafe.Pointer(cStr))
  120. ok := f(h.ptr, cStr)
  121. if ok < 0 {
  122. h.LastError()
  123. }
  124. return nil
  125. }
  126. //
  127. //end of helpers
  128. //
  129. func (h Handle) Root() (string, error) {
  130. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  131. return C.alpm_option_get_root(handle)
  132. })
  133. }
  134. func (h Handle) DBPath() (string, error) {
  135. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  136. return C.alpm_option_get_dbpath(handle)
  137. })
  138. }
  139. func (h Handle) Lockfile() (string, error) {
  140. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  141. return C.alpm_option_get_lockfile(handle)
  142. })
  143. }
  144. func (h Handle) CacheDirs() (StringList, error) {
  145. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  146. return C.alpm_option_get_cachedirs(handle)
  147. })
  148. }
  149. func (h Handle) AddCacheDir(hookDir string) error {
  150. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  151. return C.alpm_option_add_cachedir(handle, str)
  152. })
  153. }
  154. func (h Handle) SetCacheDirs(hookDirs ...string) error {
  155. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  156. return C.alpm_option_set_cachedirs(handle, l)
  157. })
  158. }
  159. func (h Handle) RemoveCacheDir(dir string) (bool, error) {
  160. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  161. return C.alpm_option_remove_cachedir(handle, str)
  162. })
  163. }
  164. func (h Handle) HookDirs() (StringList, error) {
  165. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  166. return C.alpm_option_get_hookdirs(handle)
  167. })
  168. }
  169. func (h Handle) AddHookDir(hookDir string) error {
  170. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  171. return C.alpm_option_add_hookdir(handle, str)
  172. })
  173. }
  174. func (h Handle) SetHookDirs(hookDirs ...string) error {
  175. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  176. return C.alpm_option_set_hookdirs(handle, l)
  177. })
  178. }
  179. func (h Handle) RemoveHookDir(dir string) (bool, error) {
  180. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  181. return C.alpm_option_remove_hookdir(handle, str)
  182. })
  183. }
  184. func (h Handle) LogFile() (string, error) {
  185. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  186. return C.alpm_option_get_logfile(handle)
  187. })
  188. }
  189. func (h Handle) SetLogFile(str string) error {
  190. return h.optionSetStr(str, func(handle *C.alpm_handle_t, c_str *C.char) C.int {
  191. return C.alpm_option_set_logfile(handle, c_str)
  192. })
  193. }
  194. func (h Handle) GPGDir() (string, error) {
  195. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  196. return C.alpm_option_get_gpgdir(handle)
  197. })
  198. }
  199. func (h Handle) SetGPGDir(str string) error {
  200. return h.optionSetStr(str, func(handle *C.alpm_handle_t, c_str *C.char) C.int {
  201. return C.alpm_option_set_gpgdir(handle, c_str)
  202. })
  203. }
  204. func (h Handle) UseSyslog() (bool, error) {
  205. ok := C.alpm_option_get_usesyslog(h.ptr)
  206. b := false
  207. if ok > 0 {
  208. b = true
  209. }
  210. if ok < 0 {
  211. return b, h.LastError()
  212. }
  213. return b, nil
  214. }
  215. func (h Handle) SetUseSyslog(value bool) error {
  216. var intValue C.int
  217. if value {
  218. intValue = 1
  219. }
  220. ok := C.alpm_option_set_usesyslog(h.ptr, intValue)
  221. if ok < 0 {
  222. return h.LastError()
  223. }
  224. return nil
  225. }
  226. func (h Handle) NoUpgrades() (StringList, error) {
  227. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  228. return C.alpm_option_get_noupgrades(handle)
  229. })
  230. }
  231. func (h Handle) AddNoUpgrade(hookDir string) error {
  232. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  233. return C.alpm_option_add_noupgrade(handle, str)
  234. })
  235. }
  236. func (h Handle) SetNoUpgrades(hookDirs ...string) error {
  237. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  238. return C.alpm_option_set_noupgrades(handle, l)
  239. })
  240. }
  241. func (h Handle) RemoveNoUpgrade(dir string) (bool, error) {
  242. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  243. return C.alpm_option_remove_noupgrade(handle, str)
  244. })
  245. }
  246. func (h Handle) MatchNoUpgrade(dir string) (bool, error) {
  247. return h.optionMatchList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  248. return C.alpm_option_match_noupgrade(handle, str)
  249. })
  250. }
  251. func (h Handle) NoExtracts() (StringList, error) {
  252. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  253. return C.alpm_option_get_noextracts(handle)
  254. })
  255. }
  256. func (h Handle) AddNoExtract(hookDir string) error {
  257. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  258. return C.alpm_option_add_noextract(handle, str)
  259. })
  260. }
  261. func (h Handle) SetNoExtracts(hookDirs ...string) error {
  262. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  263. return C.alpm_option_set_noextracts(handle, l)
  264. })
  265. }
  266. func (h Handle) RemoveNoExtract(dir string) (bool, error) {
  267. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  268. return C.alpm_option_remove_noextract(handle, str)
  269. })
  270. }
  271. func (h Handle) MatchNoExtract(dir string) (bool, error) {
  272. return h.optionMatchList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  273. return C.alpm_option_match_noextract(handle, str)
  274. })
  275. }
  276. func (h Handle) IgnorePkgs() (StringList, error) {
  277. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  278. return C.alpm_option_get_ignorepkgs(handle)
  279. })
  280. }
  281. func (h Handle) AddIgnorePkg(hookDir string) error {
  282. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  283. return C.alpm_option_add_ignorepkg(handle, str)
  284. })
  285. }
  286. func (h Handle) SetIgnorePkgs(hookDirs ...string) error {
  287. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  288. return C.alpm_option_set_ignorepkgs(handle, l)
  289. })
  290. }
  291. func (h Handle) RemoveIgnorePkg(dir string) (bool, error) {
  292. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  293. return C.alpm_option_remove_ignorepkg(handle, str)
  294. })
  295. }
  296. func (h Handle) IgnoreGroups() (StringList, error) {
  297. return h.optionGetList(func(handle *C.alpm_handle_t) *C.alpm_list_t {
  298. return C.alpm_option_get_ignoregroups(handle)
  299. })
  300. }
  301. func (h Handle) AddIgnoreGroup(hookDir string) error {
  302. return h.optionAddList(hookDir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  303. return C.alpm_option_add_ignoregroup(handle, str)
  304. })
  305. }
  306. func (h Handle) SetIgnoreGroups(hookDirs ...string) error {
  307. return h.optionSetList(hookDirs, func(handle *C.alpm_handle_t, l *C.alpm_list_t) C.int {
  308. return C.alpm_option_set_ignoregroups(handle, l)
  309. })
  310. }
  311. func (h Handle) RemoveIgnoreGroup(dir string) (bool, error) {
  312. return h.optionRemoveList(dir, func(handle *C.alpm_handle_t, str *C.char) C.int {
  313. return C.alpm_option_remove_ignoregroup(handle, str)
  314. })
  315. }
  316. /*func (h Handle) optionGetList(f func(*C.alpm_handle_t) *C.alpm_list_t) (StringList, error){
  317. alpmList := f(h.ptr)
  318. goList := StringList{(*list)(unsafe.Pointer(alpmList))}
  319. if alpmList == nil {
  320. return goList, h.LastError()
  321. }
  322. return goList, nil
  323. }*/
  324. //use alpm_depend_t
  325. func (h Handle) AssumeInstalled() (DependList, error) {
  326. alpmList := C.alpm_option_get_assumeinstalled(h.ptr)
  327. depList := DependList{(*list)(unsafe.Pointer(alpmList))}
  328. if alpmList == nil {
  329. return depList, h.LastError()
  330. }
  331. return depList, nil
  332. }
  333. func (h Handle) AddAssumeInstalled(dep Depend) error {
  334. cDep := convertCDepend(dep)
  335. defer freeCDepend(cDep)
  336. ok := C.alpm_option_add_assumeinstalled(h.ptr, cDep)
  337. if ok < 0 {
  338. return h.LastError()
  339. }
  340. return nil
  341. }
  342. func (h Handle) SetAssumeInstalled(deps ...Depend) error {
  343. //calling this function the first time causes alpm to set the
  344. //assumeinstalled list to a list containing go allocated alpm_depend_t's
  345. //this is bad because alpm might at some point tree to free them
  346. //i believe this is whats causing this function to misbhave
  347. //although i am not 100% sure
  348. //maybe using C.malloc to make the struct could fix the problem
  349. //pacamn does not use alpm_option_set_assumeinstalled in its source
  350. //code so anybody using this should beable to do file without it
  351. //although for the sake of completeness it would be nice to have this
  352. //working
  353. panic("This function (SetAssumeInstalled) does not work properly, please do not use. See source code for more details")
  354. var list *C.alpm_list_t
  355. for _, dep := range deps {
  356. cDep := convertCDepend(dep)
  357. defer freeCDepend(cDep)
  358. list = C.alpm_list_add(list, unsafe.Pointer(cDep))
  359. }
  360. ok := C.alpm_option_set_assumeinstalled(h.ptr, list)
  361. if ok < 0 {
  362. return h.LastError()
  363. }
  364. return nil
  365. }
  366. func (h Handle) RemoveAssumeInstalled(dep Depend) (bool, error) {
  367. //internally alpm uses alpm_list_remove to remove a alpm_depend_t from
  368. //the list
  369. //i believe this function considers items equal if they are the same
  370. //item in memeory, not just the same data
  371. //every time we convert a go Depend to a alpm_depend_c we create a new
  372. //instance of a alpm_depend_c
  373. //this means that if you add a Depend using AddAssumeInstalled then try
  374. //to remove it using the same Depend c will consider them different
  375. //items and not remove them
  376. //pacamn does not use alpm_option_set_assumeinstalled in its source
  377. //code so anybody using this should beable to do file without it
  378. //although for the sake of completeness it would be nice to have this
  379. //working
  380. panic("This function (RemoveAssumeInstalled) does not work properly, please do not use. See source code for more details")
  381. cDep := convertCDepend(dep)
  382. defer freeCDepend(cDep)
  383. ok := C.alpm_option_remove_assumeinstalled(h.ptr, cDep)
  384. if ok < 0 {
  385. return ok == 1, h.LastError()
  386. }
  387. return ok == 1, nil
  388. }
  389. func (h Handle) Arch() (string, error) {
  390. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  391. return C.alpm_option_get_arch(handle)
  392. })
  393. }
  394. func (h Handle) SetArch(str string) error {
  395. return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int {
  396. return C.alpm_option_set_arch(handle, cStr)
  397. })
  398. }
  399. func (h Handle) DeltaRatio() (float64, error) {
  400. ok := C.alpm_option_get_deltaratio(h.ptr)
  401. if ok < 0 {
  402. return float64(ok), h.LastError()
  403. }
  404. return float64(ok), nil
  405. }
  406. func (h Handle) SetDeltaRatio(ratio float64) error {
  407. ok := C.alpm_option_set_deltaratio(h.ptr, C.double(ratio))
  408. if ok < 0 {
  409. return h.LastError()
  410. }
  411. return nil
  412. }
  413. func (h Handle) CheckSpace() (bool, error) {
  414. ok := C.alpm_option_get_checkspace(h.ptr)
  415. b := false
  416. if ok > 0 {
  417. b = true
  418. }
  419. if ok < 0 {
  420. return b, h.LastError()
  421. }
  422. return b, nil
  423. }
  424. func (h Handle) SetCheckSpace(value bool) error {
  425. var cValue C.int
  426. if value {
  427. cValue = 1
  428. }
  429. ok := C.alpm_option_set_checkspace(h.ptr, cValue)
  430. if ok < 0 {
  431. return h.LastError()
  432. }
  433. return nil
  434. }
  435. func (h Handle) DBExt() (string, error) {
  436. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  437. return C.alpm_option_get_dbext(handle)
  438. })
  439. }
  440. func (h Handle) SetDBExt(str string) error {
  441. return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int {
  442. return C.alpm_option_set_dbext(handle, cStr)
  443. })
  444. }
  445. func (h Handle) GetDefaultSigLevel() (SigLevel, error) {
  446. sigLevel := C.alpm_option_get_default_siglevel(h.ptr)
  447. if sigLevel < 0 {
  448. return SigLevel(sigLevel), h.LastError()
  449. }
  450. return SigLevel(sigLevel), nil
  451. }
  452. func (h Handle) SetDefaultSigLevel(siglevel SigLevel) error {
  453. ok := C.alpm_option_set_default_siglevel(h.ptr, C.int(siglevel))
  454. if ok < 0 {
  455. return h.LastError()
  456. }
  457. return nil
  458. }
  459. func (h Handle) GetLocalFileSigLevel() (SigLevel, error) {
  460. sigLevel := C.alpm_option_get_local_file_siglevel(h.ptr)
  461. if sigLevel < 0 {
  462. return SigLevel(sigLevel), h.LastError()
  463. }
  464. return SigLevel(sigLevel), nil
  465. }
  466. func (h Handle) SetLocalFileSigLevel(siglevel SigLevel) error {
  467. ok := C.alpm_option_set_local_file_siglevel(h.ptr, C.int(siglevel))
  468. if ok < 0 {
  469. return h.LastError()
  470. }
  471. return nil
  472. }
  473. func (h Handle) GetRemoteFileSigLevel() (SigLevel, error) {
  474. sigLevel := C.alpm_option_get_remote_file_siglevel(h.ptr)
  475. if sigLevel < 0 {
  476. return SigLevel(sigLevel), h.LastError()
  477. }
  478. return SigLevel(sigLevel), nil
  479. }
  480. func (h Handle) SetRemoteFileSigLevel(siglevel SigLevel) error {
  481. ok := C.alpm_option_set_remote_file_siglevel(h.ptr, C.int(siglevel))
  482. if ok < 0 {
  483. return h.LastError()
  484. }
  485. return nil
  486. }