handle.go 15 KB

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