Skip to content

Commit

Permalink
Fix for #1 (settings shared across locations)
Browse files Browse the repository at this point in the history
Network services (e.g. IPv4 or IPv6) are stored separately under /NetworkServices - before we only copied the link rather than the settings themselves.

--HG--
extra : convert_revision : 075578d
  • Loading branch information
acdha committed Mar 11, 2009
1 parent 09b21f0 commit e787421
Showing 1 changed file with 61 additions and 29 deletions.
90 changes: 61 additions & 29 deletions bin/create-location.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,95 @@
copying the Automatic location
"""

from SystemConfiguration import \
SCPreferencesApplyChanges, \
SCPreferencesCommitChanges, \
SCPreferencesCreate, \
SCPreferencesGetValue, \
SCPreferencesPathCreateUniqueChild, \
SCPreferencesPathSetValue, \
kSCPrefSets, \
kSCPropUserDefinedName

from CoreFoundation import CFDictionaryCreateMutableCopy
from SystemConfiguration import *
from CoreFoundation import *
import sys
import re
# TODO: Use logging & OptionParser for debug level

def copy_set(path, old_id, old_set):
new_set = CFPropertyListCreateDeepCopy(None, old_set, kCFPropertyListMutableContainersAndLeaves)
new_set_path = SCPreferencesPathCreateUniqueChild(sc_prefs, path)

if not new_set_path \
or not re.match(r"^%s/[^/]+$" % path, new_set_path):
raise RuntimeError("SCPreferencesPathCreateUniqueChild() returned an invalid path for the new location: %s" % new_set_path)

return new_set_path, new_set

def main():
# Ugly but this is easiest until we refactor this into an SCPrefs class:
global sc_prefs

if len(sys.argv) != 2:
print >> sys.stderr, __doc__.strip()
sys.exit(1)

new_name = sys.argv[1]

sc_prefs = SCPreferencesCreate(None, "create_location", None)

sets = SCPreferencesGetValue(sc_prefs, kSCPrefSets)
automatic_set = None
new_name = sys.argv[1]
sc_prefs = SCPreferencesCreate(None, "create_location", None)
sets = SCPreferencesGetValue(sc_prefs, kSCPrefSets)
old_set_id = None
old_set = None

for k in sets:
if sets[k][kSCPropUserDefinedName] == new_name:
raise KeyError("A set named %s already exists" % new_name)
raise RuntimeError("A set named %s already exists" % new_name)
elif sets[k][kSCPropUserDefinedName] == "Automatic":
automatic_set = sets[k]
old_set_id = k

if not automatic_set:
if not old_set_id:
raise RuntimeError("Couldn't find Automatic set")

new_set = CFDictionaryCreateMutableCopy(None, 0, automatic_set)
old_set = sets[old_set_id]

print 'Creating "%s" using a copy of "%s"' % (new_name, old_set[kSCPropUserDefinedName])

new_set_path, new_set = copy_set("/%s" % kSCPrefSets, old_set_id, old_set)
new_set[kSCPropUserDefinedName] = new_name
new_set_path = SCPreferencesPathCreateUniqueChild(sc_prefs, "/%s" % kSCPrefSets)

if not new_set_path \
or not re.match(r"^/%s/[^/]+$" % kSCPrefSets, new_set_path) \
or new_set_path in sets:
raise RuntimeError("SCPreferencesPathCreateUniqueChild() returned an invalid path for the new location: %s" % new_set_path)
print "Old set %s:\n%s" % (old_set_id, old_set)

service_map = dict()

for old_service_id in old_set[kSCCompNetwork][kSCCompService]:
assert(
old_set[kSCCompNetwork][kSCCompService][old_service_id][kSCResvLink].startswith("/%s" % kSCPrefNetworkServices)
)

new_service_path = SCPreferencesPathCreateUniqueChild(sc_prefs, "/%s" % kSCPrefNetworkServices)
new_service_id = new_service_path.split("/")[2]
new_service_cf = CFPropertyListCreateDeepCopy(
None,
SCPreferencesGetValue(sc_prefs, kSCPrefNetworkServices)[old_service_id],
kCFPropertyListMutableContainersAndLeaves
)
SCPreferencesPathSetValue(sc_prefs, new_service_path, new_service_cf)

print 'Creating "%s" at %s using a copy of "%s"' % (new_name, new_set_path, automatic_set[kSCPropUserDefinedName])
new_set[kSCCompNetwork][kSCCompService][new_service_id] = {
kSCResvLink: new_service_path
}
del new_set[kSCCompNetwork][kSCCompService][old_service_id]

service_map[old_service_id] = new_service_id

for proto in new_set[kSCCompNetwork][kSCCompGlobal]:
new_set[kSCCompNetwork][kSCCompGlobal][proto][kSCPropNetServiceOrder] = map(
lambda k: service_map[k],
old_set[kSCCompNetwork][kSCCompGlobal][proto][kSCPropNetServiceOrder]
)

SCPreferencesPathSetValue(sc_prefs, new_set_path, new_set)

print "New Set %s:\n%s\n" % (new_set_path.split('/')[-1], new_set)

if not SCPreferencesCommitChanges(sc_prefs):
raise RuntimeError("Unable to save SystemConfiguration changes")

if not SCPreferencesApplyChanges(sc_prefs):
raise RuntimeError("Unable to apply SystemConfiguration changes")

if __name__ == '__main__':
try:
main()
except StandardError, e:
print >> sys.stderr, "ERROR: " + e.message
print >> sys.stderr, "ERROR: %s" % e.message

0 comments on commit e787421

Please sign in to comment.