Swift: How to get Console User, UID, and GID via SCDynamicStoreCopyConsoleUser? - objective-c

I am able to get the Username, UID and GID from SCDynamicStoreCopyConsoleUser using python:
#!/usr/bin/python
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
cfuser = SCDynamicStoreCopyConsoleUser( None, None, None )
print cfuser[0] # Returns console user, e.g.: myUsername
print cfuser[1] # Returns console user’s UID, e.g.: 501
print cfuser[2] # Returns console user’s GID, e.g.: 20
How can I get this same return using Swift?
Swift Declaration of SCDynamicStoreCopyConsoleUser
func SCDynamicStoreCopyConsoleUser(_ store: SCDynamicStore!,
_ uid: CMutablePointer<uid_t>,
_ gid: CMutablePointer<gid_t>) -> Unmanaged<CFString>!
My Swift Call
var uid: CMutablePointer<uid_t>!
var gid: CMutablePointer<gid_t>!
var cfuser: NSArray = [SCDynamicStoreCopyConsoleUser(nil,uid,gid)]
// the return has only one element containing the username

The Swift function SCDynamicStoreCopyConsoleUser takes a CMutablePointer<uid_t> argument which means that you have to pass the address of a uid_t variable.
Also you should check if the call succeeded (otherwise nil is returned),
and you
have to convert the returned unmanaged object as described in
Working with Cocoa Data Types:
import SystemConfiguration
var uid: uid_t = 0
var gid: gid_t = 0
if let theResult = SCDynamicStoreCopyConsoleUser(nil, &uid, &gid) {
let name = theResult.takeUnretainedValue()
println("name = \(name), uid = \(uid), gid = \(gid)")
} else {
println("failed")
}

Related

Karate | String Split for CLI output [duplicate]

I'm unsure about how I can split the response string from an already created feature to obtain the response header "Location" value.
What I've tried
1)
Feature: Create Tariff
Background:
* def result = call read('../../get-user-token.feature')
* def serviceId = call read('create-service.feature')
Scenario: Create Tariff
Given url 'https://app-dev.topbox.pro/tariff-svc/api/v1/tariffs'
And header Authorization = result.response.token_type + " " + result.response.access_token
And request
"""
{
serviceTypeId: '#(serviceId.responseHeaders['Location'].split('/')[1])',
owner: 1,
type: 0,
pencePerMile: '69.69',
minMileage: '1.00',
minCost: 5,
zoneFrom: '',
zoneTo: '',
fixedCost: 0
}
"""
When method POST
Then status 201
Which resulted in...
IntegrationTests.TestSetup.create-tariff: create-tariff.feature:10 -
net.minidev.json.parser.ParseException: Unexpected token L at position
46.
2)
Feature: Create Tariff
Background:
* def result = call read('../../get-user-token.feature')
* def serviceId = call read('create-service.feature').responseHeaders['Location'].split('/')[1]
Scenario: Create Tariff
Given url 'https://app-dev.topbox.pro/tariff-svc/api/v1/tariffs'
And header Authorization = result.response.token_type + " " + result.response.access_token
And request
"""
{
serviceTypeId: '#(serviceId)',
owner: 1,
type: 0,
pencePerMile: '69.69',
minMileage: '1.00',
minCost: 5,
zoneFrom: '',
zoneTo: '',
fixedCost: 0
}
"""
When method POST
Then status 201
Which resulted in...
failed features: IntegrationTests.TestSetup.create-tariff: -unknown-:5
- javascript evaluation failed: read('create-service.feature').responseHeaders['Location'].split('/')1,
TypeError: Cannot read property "Location" from undefined in at
line number 1
NOTE
The specified feature "create-service.feature" does indeed work when isolated and does produce the response header, as shown below
Use lastIndexOf instead of split:
* def location = responseHeaders['Location'][0]
* def serviceId = location.substring(location.lastIndexOf('/') + 1)
You need to use a Javascript function : https://github.com/intuit/karate#javascript-functions
* def greeter = function(name){ return 'hello ' + name }
* assert greeter('Bob') == 'hello Bob'
EDIT:
* def service = { key : "someinfo/myServiceId"}
* def func = function(service){return service.key.split('/')[1]}
* def serviceId = func(service)
* match serviceId == "myServiceId"
I think the first error is due to single quotes inside your expression, try escaping that
like,
And request
"""
{
serviceTypeId: '#(serviceId.responseHeaders.Location[0].split(\'/\')[1])',
owner: 1,
type: 0,
pencePerMile: '69.69',
minMileage: '1.00',
minCost: 5,
zoneFrom: '',
zoneTo: '',
fixedCost: 0
}
"""
Edit: Just now noted each value in responseHeader has a list type value so access it like Location[0]
And your second Approach should be something like this,
* def serviceId = call read('create-service.feature').responseHeaders.Location[0].split('/')[1]
I just face the same issue (.split is not a function), and in my case, I need to convert the data to string first, before using split function.
Here is the custom code from adrien answer:
* def service = { key : "someinfo/myServiceId"}
* def func = function(service){return service.key.toString().split('/')[1]}

How to list all assets (groupId, name, size) in a Nexus3 repository?

I know it is very simple to do in OrientDB :
select * from asset where bucket.repository_name = 'my-repo-release';
but I need to get this list remotely, not in local orientdb console, so I need a groovy script and I can't find it anywhere.
Here is the example script :
https://github.com/sonatype-nexus-community/nexus-scripting-examples
it can be found in the "nexus-script-example" project :
import org.sonatype.nexus.repository.storage.Asset
import org.sonatype.nexus.repository.storage.Query
import org.sonatype.nexus.repository.storage.StorageFacet
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
def assetListFile = new File('/tmp/assetListFile.txt')
def request = new JsonSlurper().parseText("{\"repoName\":\"maven-releases\",\"startDate\":\"2016-01-01\"}")
assert request.repoName: 'repoName parameter is required'
assert request.startDate: 'startDate parameter is required, format: yyyy-mm-dd'
log.info("Gathering Asset list for repository: ${request.repoName} as of startDate: ${request.startDate}")
def repo = repository.repositoryManager.get(request.repoName)
StorageFacet storageFacet = repo.facet(StorageFacet)
def tx = storageFacet.txSupplier().get()
try {
tx.begin()
Iterable<Asset> assets = tx.findAssets(Query.builder().where('last_updated > ').param(request.startDate).build(), [repo])
assets.each {Asset asset ->
assetListFile << asset.name() + '\n'
}
}
finally {
tx.close()
}
All properties of an asset (object org.sonatype.nexus.repository.storage.Asset) are accessible, including asset.size().

How to invoke swift function from lldb using address (pointer)?

I'm playing with lldb and I'm trying to call my swift static function. I was able to find its details in image, however I have no idea how to call it and pass arguments.
My output:
(lldb) image lookup -vs $S5project19ViewControllerUtilsC07setRootbC010storyboard13withAnimationySo12UIStoryboardC_SbtFZ
1 symbols match '$S5project19ViewControllerUtilsC07setRootbC010storyboard13withAnimationySo12UIStoryboardC_SbtFZ' in /Users/user/Library/Developer/CoreSimulator/Devices/DC7A5199-424E-4E38-A8A8-CB99C7D8CF82/data/Containers/Bundle/Application/BE7BB249-DB64-4228-B64E-EB430BCCE29E/project.app/project:
Address: project[0x00000002000fc970] (project.__TEXT.__text + 1027840)
Summary: project`static project.ViewControllerUtils.setRootViewController(storyboard: __C.UIStoryboard, withAnimation: Swift.Bool) -> () at ViewControllerUtils.swift:7
Module: file = "/Users/user/Library/Developer/CoreSimulator/Devices/DC7A5199-424E-4E38-A8A8-CB99C7D8CF82/data/Containers/Bundle/Application/BE7BB249-DB64-4228-B64E-EB430BCCE29E/project.app/project", arch = "x86_64"
CompileUnit: id = {0x00000000}, file = "/Users/user/mobile/company/iOS/project/project/Utils/ViewControllerUtils.swift", language = "swift"
Function: id = {0x7700000075}, name = "static project.ViewControllerUtils.setRootViewController(storyboard: __C.UIStoryboard, withAnimation: Swift.Bool) -> ()", mangled = "$S5project19ViewControllerUtilsC07setRootbC010storyboard13withAnimationySo12UIStoryboardC_SbtFZ", range = [0x000000010bd0c780-0x000000010bd0c82e)
FuncType: id = {0x7700000075}, byte-size = 8, decl = ViewControllerUtils.swift:7, compiler_type = "(UIKit.UIStoryboard, Swift.Bool) -> ()
"
Blocks: id = {0x7700000075}, range = [0x10bd0c780-0x10bd0c82e)
LineEntry: [0x000000010bd0c780-0x000000010bd0c79d): /Users/user/mobile/company/iOS/project/project/Utils/ViewControllerUtils.swift:7
Symbol: id = {0x00002a71}, range = [0x000000010ac0c780-0x000000010ac0c830), name="static project.ViewControllerUtils.setRootViewController(storyboard: __C.UIStoryboard, withAnimation: Swift.Bool) -> ()", mangled="$S5project19ViewControllerUtilsC07setRootbC010storyboard13withAnimationySo12UIStoryboardC_SbtFZ"
Variable: id = {0x6600000092}, name = "storyboard", type = "UIKit.UIStoryboard", location = DW_OP_fbreg(-16), decl = ViewControllerUtils.swift:7
Variable: id = {0x66000000a0}, name = "withAnimation", type = "Swift.Bool", location = DW_OP_fbreg(-24), decl = ViewControllerUtils.swift:7
Variable: id = {0x66000000ae}, name = "self", type = "#thick project.ViewControllerUtils.Type", location = DW_OP_fbreg(-32), decl = ViewControllerUtils.swift:7
Source code:
final class ViewControllerUtils {
static func setRootViewController(storyboard: UIStoryboard, withAnimation: Bool) {
setRootViewController(window: UIApplication.shared.keyWindow, storyboard: storyboard, withAnimation: withAnimation)
}
}
I know I could switch to Swift and invoke something like this:
expression -l swift -O -- ViewControllerUtils.setRootViewController(storyboard: UIKit.UIStoryboard(name: "Main", bundle: nil), withAnimation: true)
But I would like to learn how to invoke a function using its address or symbol without referencing to specific class like above.
I have found the solution.
Take address from range: Symbol: id = {0x00002a71}, range = [0x000000010ac0c780-0x000000010ac0c830) this one: 0x000000010ac0c780.
Import UIKit (lldb) po import UIKit
Create Storyboard:
(lldb) p UIStoryboard(name: "Main", bundle: nil)
(UIStoryboard) $R2 = 0x00006000006c8200 {
ObjectiveC.NSObject = {
isa = UIStoryboard
}
}
Cast raw address to function and invoke it using created Storyboard variable $R2:
(lldb) po unsafeBitCast(0x000000010ac0c780, to: (#convention(c)(UIKit.UIStoryboard, Bool) -> ()).self)($R2, true)
Here you can read also an interesting example of importing C function: Swift: How to call a C function loaded from a dylib

How to read file comment field

In OS X Finder there is 'Comment' file property. It can be checked in finder by adding 'Comment' column or edited/checked after right clicking on file or folder and selecting 'Get info'.
How to read this value in swift or objective-c?
I checked already NSURL and none of them seems to be the right ones
Do not use the low-level extended attributes API to read Spotlight metadata. There's a proper Spotlight API for that. (It's called the File Metadata API.) Not only is it a pain in the neck, there's no guarantee that Apple will keep using the same extended attribute to store this information.
Use MDItemCreateWithURL() to create an MDItem for the file. Use MDItemCopyAttribute() with kMDItemFinderComment to obtain the Finder comment for the item.
Putting the pieces together (Ken Thomases reading answer above and writing answer link) you can extend URL with a computed property with a getter and a setter to read/write comments to your files:
update: Xcode 8.2.1 • Swift 3.0.2
extension URL {
var finderComment: String? {
get {
guard isFileURL else { return nil }
return MDItemCopyAttribute(MDItemCreateWithURL(kCFAllocatorDefault, self as CFURL), kMDItemFinderComment) as? String
}
set {
guard isFileURL, let newValue = newValue else { return }
let script = "tell application \"Finder\"\n" +
String(format: "set filePath to \"%#\" as posix file \n", absoluteString) +
String(format: "set comment of (filePath as alias) to \"%#\" \n", newValue) +
"end tell"
guard let appleScript = NSAppleScript(source: script) else { return }
var error: NSDictionary?
appleScript.executeAndReturnError(&error)
if let error = error {
print(error[NSAppleScript.errorAppName] as! String)
print(error[NSAppleScript.errorBriefMessage] as! String)
print(error[NSAppleScript.errorMessage] as! String)
print(error[NSAppleScript.errorNumber] as! NSNumber)
print(error[NSAppleScript.errorRange] as! NSRange)
}
}
}
}
As explained in the various answers to Mac OS X : add a custom meta data field to any file,
Finder comments can be read and set programmatically with getxattr() and setxattr(). They are stored as extended attribute
"com.apple.metadata:kMDItemFinderComment", and the value is a property
list.
This works even for files not indexed by Spotlight, such as those on a network server volume.
From the Objective-C code here
and here I made this simple Swift function
to read the Finder comment (now updated for Swift 4 and later):
func finderComment(url : URL) -> String? {
let XAFinderComment = "com.apple.metadata:kMDItemFinderComment"
let data = url.withUnsafeFileSystemRepresentation { fileSystemPath -> Data? in
// Determine attribute size:
let length = getxattr(fileSystemPath, XAFinderComment, nil, 0, 0, 0)
guard length >= 0 else { return nil }
// Create buffer with required size:
var data = Data(count: length)
// Retrieve attribute:
let result = data.withUnsafeMutableBytes { [count = data.count] in
getxattr(fileSystemPath, XAFinderComment, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else { return nil }
return data
}
// Deserialize to String:
guard let data = data, let comment = try? PropertyListSerialization.propertyList(from: data,
options: [], format: nil) as? String else {
return nil
}
return comment
}
Example usage:
let url = URL(fileURLWithPath: "/path/to/file")
if let comment = finderComment(url: url) {
print(comment)
}
The function returns an optional string which is nil if the file
has no Finder comment, or if anything went wrong while retrieving it.

ScalikeJDBC: Connection pool is not yet initialized.(name:'default)

I'm playing with ScalikeJdbc library. I want to retrieve the data from PostgreSQL database. The error I get is quite strange for me. Even if I configure manually the CP:
val poolSettings = new ConnectionPoolSettings(initialSize = 100, maxSize = 100)
ConnectionPool.singleton("jdbc:postgresql://localhost:5432/test", "user", "pass", poolSettings)
I still see the error. Here is my DAO:
class CustomerDAO {
case class Customer(id: Long, firstname: String, lastname: String)
object Customer extends SQLSyntaxSupport[Customer]
val c = Customer.syntax("c")
def findById(id: Long)(implicit session: DBSession = Customer.autoSession) =
withSQL {
select.from(Customer as c)
}.map(
rs => Customer(
rs.int("id"),
rs.string("firstname"),
rs.string("lastname")
)
).single.apply()
}
The App:
object JdbcTest extends App {
val dao = new CustomerDAO
val res: Option[dao.Customer] = dao.findById(2)
}
My application.conf file
# PostgreSQL
db.default.driver = "org.postgresql.Driver"
db.default.url = "jdbc:postgresql://localhost:5432/test"
db.default.user = "user"
db.default.password = "pass"
# Connection Pool settings
db.default.poolInitialSize = 5
db.default.poolMaxSize = 7
db.default.poolConnectionTimeoutMillis = 1000
The error:
Exception in thread "main" java.lang.IllegalStateException: Connection pool is not yet initialized.(name:'default)
at scalikejdbc.ConnectionPool$$anonfun$get$1.apply(ConnectionPool.scala:57)
at scalikejdbc.ConnectionPool$$anonfun$get$1.apply(ConnectionPool.scala:55)
at scala.Option.getOrElse(Option.scala:120)
at scalikejdbc.ConnectionPool$.get(ConnectionPool.scala:55)
at scalikejdbc.ConnectionPool$.apply(ConnectionPool.scala:46)
at scalikejdbc.NamedDB.connectionPool(NamedDB.scala:20)
at scalikejdbc.NamedDB.db$lzycompute(NamedDB.scala:32)
What did I miss?
To load application.conf, scalikejdbc-config's DBs.setupAll() should be called in advance.
http://scalikejdbc.org/documentation/configuration.html#scalikejdbc-config
https://github.com/scalikejdbc/hello-scalikejdbc/blob/9d21ec7ddacc76977a7d41aa33c800d89fedc7b6/test/settings/DBSettings.scala#L3-L22
In my case I omit play.modules.enabled += "scalikejdbc.PlayModule" in conf/application.conf using ScalikeJDBC Play support...