Skip to content

Instantly share code, notes, and snippets.

@timthelion
Created May 28, 2014 16:21
Show Gist options
  • Select an option

  • Save timthelion/28d0a4d320910965422f to your computer and use it in GitHub Desktop.

Select an option

Save timthelion/28d0a4d320910965422f to your computer and use it in GitHub Desktop.
Device JSON Marshalers
package jsonDevices
import (
"encoding/json"
"fmt"
"os"
)
type JSONDevice struct {
Type string `json:"type"`
Path string `json:"path"` // It is fine if this is an empty string in the case that you are using Wildcards
MajorNumber int64 `json:"major_number"` // Use the wildcard constant for wildcards.
MinorNumber int64 `json:"minor_number"` // Use the wildcard constant for wildcards.
CgroupPermissions string `json:"cgroup_permissions"` // Typically just "rwm"
FileMode string `json:"file_mode"` // The permission bits of the file's mode
}
func (device Device) MarshalJSON() ([]byte,error){
jsonDevice := new(JSONDevice)
switch device.Type{
case 'c':
jsonDevice.Type="character"
case 'b':
jsonDevice.Type="block"
default:
return nil,fmt.Errorf("Invalid device type %c",device.Type)
}
jsonDevice.Path = device.Path
jsonDevice.MajorNumber = device.MajorNumber
jsonDevice.MinorNumber = device.MinorNumber
jsonDevice.CgroupPermissions = device.CgroupPermissions
jsonDevice.FileMode = buildFileModeString(device.FileMode)
return json.Marshal(jsonDevice)
}
func buildFileModeString(fileMode os.FileMode) string{
fileModeString := []byte("rwxrwxrwx")
// we go through the string blanking out(with '-') the permissions that are denied.
for i := uint(0); i < 9; i++{
if (fileMode & (1 << i)) == 0{
fileModeString[i] = '-'
}
}
return string(fileModeString)
}
func (device Device) UnmarshalJSON(input []byte) error {
jsonDevice := new(JSONDevice)
err := json.Unmarshal(input,jsonDevice)
if err != nil {
return err
}
switch jsonDevice.Type{
case "character":
device.Type = 'c'
case "block":
device.Type = 'b'
default:
return fmt.Errorf("Invalid device type: %s",jsonDevice.Type)
}
device.Path = jsonDevice.Path
device.MajorNumber = jsonDevice.MajorNumber
device.MinorNumber = jsonDevice.MinorNumber
device.CgroupPermissions = jsonDevice.CgroupPermissions
if len(jsonDevice.FileMode) != 9{
return fmt.Errorf("Invalid file mode for device: %s",jsonDevice.FileMode)
}
modeSegment,err := readModeSegment(jsonDevice.FileMode[0:])
if err != nil{
return fmt.Errorf("Unable to parse file mode %s: %s",jsonDevice.FileMode,err)
}
device.FileMode |= os.FileMode(modeSegment << 6)
modeSegment,err = readModeSegment(jsonDevice.FileMode[3:])
if err != nil{
return fmt.Errorf("Unable to parse file mode %s: %s",jsonDevice.FileMode,err)
}
device.FileMode |= os.FileMode(modeSegment << 3)
modeSegment,err = readModeSegment(jsonDevice.FileMode[6:])
if err != nil{
return fmt.Errorf("Unable to parse file mode %s: %s",jsonDevice.FileMode,err)
}
device.FileMode |= os.FileMode(modeSegment)
return nil
}
func readModeSegment(segment string) (uint32, error){
modeSegment := uint32(0)
set,err := readModeFlag(segment[0],'r')
if err != nil{
return 0,err
}
if set{
modeSegment |= 1
}
set,err = readModeFlag(segment[1],'w')
if err != nil{
return 0,err
}
if set{
modeSegment |= 2
}
set,err = readModeFlag(segment[2],'x')
if err != nil{
return 0,err
}
if set{
modeSegment |= 4
}
return modeSegment,nil
}
func readModeFlag(flag byte,normalSetValue byte) (bool,error){
switch flag{
case normalSetValue:
return true,nil
case '-':
return false,nil
default:
return false, fmt.Errorf("Unexpected file permission %c, expected %c or '-'.", flag,normalSetValue)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment