handle.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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. func (h *Handle) SetAssumeInstalled(deps []Depend) error {
  312. //calling this function the first time causes alpm to set the
  313. //assumeinstalled list to a list containing go allocated alpm_depend_t's
  314. //this is bad because alpm might at some point tree to free them
  315. //i believe this is whats causing this function to misbhave
  316. //although i am not 100% sure
  317. //maybe using C.malloc to make the struct could fix the problem
  318. //pacamn does not use alpm_option_set_assumeinstalled in its source
  319. //code so anybody using this should beable to do file without it
  320. //although for the sake of completeness it would be nice to have this
  321. //working
  322. panic("This function (SetAssumeInstalled) does not work properly, please do not use. See source code for more details")
  323. var list *C.alpm_list_t
  324. for _, dep := range deps {
  325. cDep := convertCDepend(dep)
  326. defer freeCDepend(cDep)
  327. list = C.alpm_list_add(list, unsafe.Pointer(cDep))
  328. }
  329. ok := C.alpm_option_set_assumeinstalled(h.ptr, list)
  330. if ok < 0 {
  331. return h.LastError()
  332. }
  333. return nil
  334. }
  335. func (h *Handle) RemoveAssumeInstalled(dep Depend) (bool, error) {
  336. //internally alpm uses alpm_list_remove to remove a alpm_depend_t from
  337. //the list
  338. //i believe this function considers items equal if they are the same
  339. //item in memeory, not just the same data
  340. //every time we convert a go Depend to a alpm_depend_c we create a new
  341. //instance of a alpm_depend_c
  342. //this means that if you add a Depend using AddAssumeInstalled then try
  343. //to remove it using the same Depend c will consider them different
  344. //items and not remove them
  345. //pacamn does not use alpm_option_set_assumeinstalled in its source
  346. //code so anybody using this should beable to do file without it
  347. //although for the sake of completeness it would be nice to have this
  348. //working
  349. panic("This function (RemoveAssumeInstalled) does not work properly, please do not use. See source code for more details")
  350. cDep := convertCDepend(dep)
  351. defer freeCDepend(cDep)
  352. ok := C.alpm_option_remove_assumeinstalled(h.ptr, cDep)
  353. if ok < 0 {
  354. return ok == 1, h.LastError()
  355. }
  356. return ok == 1, nil
  357. }
  358. func (h *Handle) Arch() (string, error) {
  359. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  360. return C.alpm_option_get_arch(handle)
  361. })
  362. }
  363. func (h *Handle) SetArch(str string) error {
  364. return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int {
  365. return C.alpm_option_set_arch(handle, cStr)
  366. })
  367. }
  368. func (h *Handle) DeltaRatio() (float64, error) {
  369. ok := C.alpm_option_get_deltaratio(h.ptr)
  370. if ok < 0 {
  371. return float64(ok), h.LastError()
  372. }
  373. return float64(ok), nil
  374. }
  375. func (h *Handle) SetDeltaRatio(ratio float64) error {
  376. ok := C.alpm_option_set_deltaratio(h.ptr, C.double(ratio))
  377. if ok < 0 {
  378. return h.LastError()
  379. }
  380. return nil
  381. }
  382. // LocalDB returns the local database relative to the given handle.
  383. func (h *Handle) LocalDB() (*DB, error) {
  384. db := C.alpm_get_localdb(h.ptr)
  385. if db == nil {
  386. return nil, h.LastError()
  387. }
  388. return &DB{db, *h}, nil
  389. }
  390. // SyncDBs returns list of Synced DBs.
  391. func (h *Handle) SyncDBs() (DBList, error) {
  392. dblist := C.alpm_get_syncdbs(h.ptr)
  393. if dblist == nil {
  394. return DBList{nil, *h}, h.LastError()
  395. }
  396. dblistPtr := unsafe.Pointer(dblist)
  397. return DBList{(*list)(dblistPtr), *h}, nil
  398. }
  399. func (h *Handle) CheckSpace() (bool, error) {
  400. ok := C.alpm_option_get_checkspace(h.ptr)
  401. b := false
  402. if ok > 0 {
  403. b = true
  404. }
  405. if ok < 0 {
  406. return b, h.LastError()
  407. }
  408. return b, nil
  409. }
  410. func (h *Handle) SetCheckSpace(value bool) error {
  411. var cValue C.int
  412. if value {
  413. cValue = 1
  414. }
  415. ok := C.alpm_option_set_checkspace(h.ptr, cValue)
  416. if ok < 0 {
  417. return h.LastError()
  418. }
  419. return nil
  420. }
  421. func (h *Handle) DBExt() (string, error) {
  422. return h.optionGetStr(func(handle *C.alpm_handle_t) *C.char {
  423. return C.alpm_option_get_dbext(handle)
  424. })
  425. }
  426. func (h *Handle) SetDBExt(str string) error {
  427. return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int {
  428. return C.alpm_option_set_dbext(handle, cStr)
  429. })
  430. }
  431. func (h *Handle) GetDefaultSigLevel() (SigLevel, error) {
  432. sigLevel := C.alpm_option_get_default_siglevel(h.ptr)
  433. if sigLevel < 0 {
  434. return SigLevel(sigLevel), h.LastError()
  435. }
  436. return SigLevel(sigLevel), nil
  437. }
  438. func (h *Handle) SetDefaultSigLevel(siglevel SigLevel) error {
  439. ok := C.alpm_option_set_default_siglevel(h.ptr, C.int(siglevel))
  440. if ok < 0 {
  441. return h.LastError()
  442. }
  443. return nil
  444. }
  445. func (h *Handle) GetLocalFileSigLevel() (SigLevel, error) {
  446. sigLevel := C.alpm_option_get_local_file_siglevel(h.ptr)
  447. if sigLevel < 0 {
  448. return SigLevel(sigLevel), h.LastError()
  449. }
  450. return SigLevel(sigLevel), nil
  451. }
  452. func (h *Handle) SetLocalFileSigLevel(siglevel SigLevel) error {
  453. ok := C.alpm_option_set_local_file_siglevel(h.ptr, C.int(siglevel))
  454. if ok < 0 {
  455. return h.LastError()
  456. }
  457. return nil
  458. }
  459. func (h *Handle) GetRemoteFileSigLevel() (SigLevel, error) {
  460. sigLevel := C.alpm_option_get_remote_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) SetRemoteFileSigLevel(siglevel SigLevel) error {
  467. ok := C.alpm_option_set_remote_file_siglevel(h.ptr, C.int(siglevel))
  468. if ok < 0 {
  469. return h.LastError()
  470. }
  471. return nil
  472. }