handle.go 15 KB

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