17 Commits

Author SHA1 Message Date
eleksir
9d3bc186cc Fix styling of LA block 2024-09-14 00:59:02 +03:00
eleksir
4c19fa2446 Update deps 2024-09-13 23:28:48 +03:00
eleksir
03926f47c4 Always setup default values even if module that uses it is disabled 2024-09-13 23:27:36 +03:00
eleksir
1485354b6c Do not try to close connection if it is not opened in VPNTCPCheck() 2024-09-13 22:02:28 +03:00
eleksir
0fd5ed87a2 Update deps 2024-04-22 23:09:48 +03:00
eleksir
b36f1fd7d7 Add sig{quit,term,int} handler that just quits application 2024-04-22 23:05:07 +03:00
eleksir
87361a4e6c Fix comment 2024-04-22 23:04:17 +03:00
eleksir
6047399fc7 Add examples of configs 2024-03-14 00:52:38 +03:00
eleksir
35ec64cbbc Update sample config 2024-03-14 00:52:38 +03:00
eleksir
bb797d75b4 More pulseaudio settings, fix formatting for indicator boxes
* Add setting that defines whether to exit pulseaudio daemon or not
* Fix styling of all indicators (use font settings instead of default box settings)
* Set defaults for battery, clock and volume indicators
2024-03-14 00:52:38 +03:00
eleksir
92bddadd9d Fix formatting issues for some indicator boxes, respect font setting for separators 2024-03-14 00:52:38 +03:00
eleksir
d47ce88c0d Use async handler instead of applying sound volume in stdin parser 2024-03-14 00:52:38 +03:00
eleksir
bf9893feba Print to i3bar asynchronously 2024-03-14 00:52:38 +03:00
eleksir
4919f74184 Try to gracefully quit pulseaudio daemon if it is not responding 2024-03-14 00:51:47 +03:00
eleksir
5770f9106e Explicitly set color and background attributes for all <span> tags 2024-01-16 21:59:04 +03:00
eleksir
95356ed547 Set block right separator size correctly, according config 2024-01-16 21:19:17 +03:00
eleksir
418216391b Set border width to 0 on all blocks except buttons 2024-01-16 20:51:55 +03:00
156 changed files with 14102 additions and 6056 deletions

View File

@@ -57,17 +57,20 @@ func UpdateBatteryInfo() {
case ch > 85:
if Conf.Battery.ChargeColor.Full == "" {
chStr = fmt.Sprintf(
"<span font='%s' size='%s'>% 3d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Full,
ch,
)
} else {
chStr = fmt.Sprintf(
`<span font='%s' size='%s' foreground='%s'>% 3d%%</span>`,
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.Full,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Full,
ch,
)
}
@@ -75,17 +78,20 @@ func UpdateBatteryInfo() {
case ch < 85 && ch > 40:
if Conf.Battery.ChargeColor.AlmostFull == "" {
chStr = fmt.Sprintf(
"<span font='%s' size='%s'>% 3d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Full,
ch,
)
} else {
chStr = fmt.Sprintf(
`<span font='%s' size='%s' foreground='%s'>% 3d%%</span>`,
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.AlmostFull,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.AlmostFull,
ch,
)
}
@@ -93,17 +99,20 @@ func UpdateBatteryInfo() {
case ch <= 40 && ch >= 10:
if Conf.Battery.ChargeColor.AlmostEmpty == "" {
chStr = fmt.Sprintf(
"<span font='%s' size='%s'>% 3d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Full,
ch,
)
} else {
chStr = fmt.Sprintf(
`<span font='%s' size='%s' foreground='%s'>% 3d%%</span>`,
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.AlmostEmpty,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.AlmostEmpty,
ch,
)
}
@@ -111,31 +120,40 @@ func UpdateBatteryInfo() {
case ch < 10:
if Conf.Battery.ChargeColor.Empty == "" {
chStr = fmt.Sprintf(
"<span font='%s' size='%s'>% 3d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Full,
ch,
)
} else {
chStr = fmt.Sprintf(
`<span font='%s' size='%s' foreground='%s'>% 3d%%</span>`,
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.Empty,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
Conf.Battery.ChargeColor.Empty,
ch,
)
}
}
battsInfo += fmt.Sprintf(
"<span font='%s' size='%s'>%s</span><span font='%s' size='%s'>B%d </span>%s<span font='%s' size='%s'> %s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span><span color='%s' background='%s' font='%s' size='%s'>B%d </span>%s<span color='%s' background='%s' font='%s' size='%s'> %s</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.SymbolFont,
Conf.Battery.SymbolFontSize,
Conf.Battery.Symbol,
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
i,
chStr,
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
status,

2285
config.go

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,793 @@
{
// Memory stats
"mem" : {
"enabled": true,
// If omitted set to default color defined up here.
"color": "#ffffff",
// If omitted set to default background color defined up here.
"background": "#008099",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "large",
// Do we show used swap megs?
"show_swap": false,
// Re-define separator parameters for net-if block here.
"separator" : {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#000000",
// If omitted set to default background color defined for separator up here.
"background": "#008099",
// If omitted set to default symbol defined for separator up here.
"symbol": " ",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "large"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#008099",
// If omitted set to default background color defined for separator up here.
"background": "#fae864",
// If omitted set to default symbol defined for separator up here.
"symbol": " ",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "large"
}
}
},
// Load Average
"la" : {
"enabled": true,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#fae864",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "x-large",
// Re-define separator parameters for net-if block here.
"separator" : {
"left": {
// Set to false if omitted.
"enabled": false,
// If omitted set to default color defined for separator up here.
"color": "#e00000",
// If omitted set to default background color defined for separator up here.
"background": "#e00000",
// If omitted set to default symbol defined for separator up here.
"symbol": "",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "large"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#fae864",
// If omitted set to default background color defined for separator up here.
"background": "#5bde52",
// If omitted set to default symbol defined for separator up here.
"symbol": " ",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "large"
}
}
},
"net-if" : {
"enabled" : false,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#000000",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "medium",
// Net interface down symbol color, in html notation.
"down_color" : "red",
// Net interface up symbol color, in html notation.
"up_color" : "green",
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
},
"if" : [
{
// Name as it displayed on i3bar
"name" : "eth0",
// Directory containing net if status files
"dir" : "/sys/class/net/eth0"
}
]
},
// OpenVPN status. Note that directive status in openvpn.conf should point to state file and *update* its timestamp at
// least as frequent as mtime_threshold in seconds.
"vpn": {
"enabled": false,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#000000",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "medium",
// Status file location. Plugin will be disabled if this value omitted.
"statusfile" : "/tmp/openvpn-status.stat",
// mtime check period.
"mtime_threshold": 10,
// Vpn down symbol color, in html notation.
"down_color" : "red",
// Vpn up symbol color, in html notation.
"up_color" : "green",
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "▶",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
},
// Also we can tcp-ping some service inside vpn network to ensure that connection is not stoned.
"tcp_check" : {
"enabled": false,
"host": "somehost.tld",
"port": 443,
"timeout" : 3
}
},
// Simple sound volume indicator
"simple-volume-pa": {
"enabled": false,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#666666",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "large",
"symbol": "🔊",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of the relative sizes
// ‘smaller’ or ‘larger’. If omitted set to value of simple-volume-pa.font_size by default.
"symbol_font_size": "large",
// If not defined - will be "true"
"right_click_cmd": ["pavucontrol"],
// Change volume step in %, if not configured it is 5
"step": 3,
// We'll change volume level with mouse wheel. Under X11 it is mapped to some buttons, typically 4 and 5 (z-axis).
// If omited, default value is 4
"wheel_up": 4,
// If omited, default value is 5
"wheel_down": 5,
// Maximum sound volume, can be over 100%, but sould not be :) Default value 100 if not set.
"max_volume_limit": 120,
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": false,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "▶",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": false,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
}
},
// Just clock
"clock": {
"enabled" : true,
// If omitted set to default color defined up here.
"color": "#000000",
// If omitted set to default background color defined up here.
"background": "#5bde52",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "large",
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": false,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "▶",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#5bde52",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": " ",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "large"
}
},
"left_click" : {
"enabled" : false,
// cmd is array of command itself and its arguments
"cmd" : [ "orage" ]
},
"right_click" : {
"enabled" : false,
"cmd" : [ "true" ]
}
},
// Battery, useful for laptops
"battery": {
"enabled": false,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#000000",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "medium",
// If omitted "⚡" (no quotes) is used.
"symbol": "⚡",
// If omitted battery.font is used.
"symbol_font" : "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of the relative sizes
// ‘smaller’ or ‘larger’. If omitted set to value of simple-volume-pa.font_size by default.
"symbol_font_size": "large",
"charge_color": {
// colors in html notation
"full": "green",
"empty": "red",
"almost_full": "yellow",
"almost_empty": "orange"
},
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "▶",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
}
},
// CPU Temperature monitor, shows average value among given sources
"cpu_temp": {
"enabled": false,
// If omitted set to default color defined up here.
"color": "#3e78fd",
// If omitted set to default background color defined up here.
"background": "#000000",
// If omitted set to default font defined up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
"font_size": "medium",
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "▶",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
},
// Files in sysfs that contains cpu temperatures
"file": [
"/sys/class/hwmon/hwmon4/temp2_input",
"/sys/class/hwmon/hwmon4/temp3_input",
"/sys/class/hwmon/hwmon4/temp4_input",
"/sys/class/hwmon/hwmon4/temp5_input",
"/sys/class/hwmon/hwmon4/temp6_input",
"/sys/class/hwmon/hwmon4/temp7_input"
]
},
// Intended mainly for use with desktop notifications
// Because it inherits all env vars from i3, it can intercat with dbus and other
// such user session services.
"cron" : {
"enabled" : false,
"tasks" : [
{
// Time in crontab notation
"time" : "55 23 * * *",
"cmd" : [
"notify-send", "Sleeping Time!", "Take a nap."
]
},
{
// time in crontab format
"time" : "55 12 * * 2,4",
// commands as it should be invoked in bash script
"cmd" : [
"notify-send", "Pizza time!", "M-m-m, tasty!"
]
}
]
},
// Whether to display Application Buttons.
"app_buttons": {
"enabled": true,
// Re-define separator parameters for net-if block here.
"separator": {
"left": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "-",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
},
"right": {
// Set to false if omitted.
"enabled": true,
// If omitted set to default color defined for separator up here.
"color": "#3e78fd",
// If omitted set to default background color defined for separator up here.
"background": "#000000",
// If omitted set to default symbol defined for separator up here.
"symbol": "◀",
// If omitted set to default font defined for separator up here.
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
"font_size": "medium"
}
},
},
// Buttons - application launch "buttons"
"apps": [
{
// Text dispalyed on button
"full_text" : "📂",
// Internal name, can be any string, but unique for each app button
"name" : "thunar",
// Command itself
"cmd" : "thunar",
// Array of command args, optional
"args": [ "." ],
// Regexp that match with Instance component of WM_CLASS(STRING) of xprop output
"instance": "^thunar$",
// Regexp that match with Class component of WM_CLASS(STRING) of xprop output
"class": "^Thunar$",
// text color in html notation
"color": "#ffa500",
// background color in html notation
"background" : "#000000",
// border color in html notation
"border": "#666666",
// border color if there is at least one window with given Instance and/or Class exist
"border_active": "#3e78fd",
// Vertical line between objects on bar - if omitted true value is assumed by i3bar, but we set it to false
// in that case. It is limitation of golang json parser.
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " ♬ ",
"name" : "deadbeef",
"cmd" : "deadbeef",
"instance" : "^deadbeef$",
"class" : "^Deadbeef$",
"color" : "#00aa33",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Term ",
"name" : "xterm",
"cmd" : "xterm",
"instance" : "^xterm$",
"class" : "^XTerm$",
"color" : "#666666",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Ff ",
"name" : "firefox",
"cmd" : "firefox",
"instance" : "^Navigator$",
"class" : "^Firefox$",
"color" : "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " C ",
"name" : "chrome",
"cmd" : "chrome",
"instance" : "^google-chrome$",
"class" : "^Google-chrome$",
"color" : "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " @ ",
"name" : "thunderbird",
"cmd" : "thunderbird",
"instance" : "^Mail$",
"class" : "^Thunderbird$",
"color" : "#006994",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Tg ",
"name" : "telegram",
"cmd" : "Telegram",
"instance" : "^Telegram$",
"class" : "^TelegramDesktop$",
"color" : "#5a8850",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " T ",
"name" : "mousepad",
"cmd" : "mousepad",
"instance" : "^mousepad$",
"class" : "^Mousepad$",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
}
]
}

View File

@@ -0,0 +1,438 @@
{
// Default text and *block* border colors. If not set #3e78fd is used.
"color" : "#3e78fd",
// Default backbround color. If not set value of #edeceb is used.
"background" : "#000000",
"separator": {
"left": {
"enabled": false,
"color": "#3e78fd",
"background": "#000000",
"symbol": "|",
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’
"font_size": "medium"
},
"right": {
// False if value omitted
"enabled": false,
// Used #edeceb as default if value omitted
"color": "#3e78fd",
// If not set #3e78fd is used.
"background": "#000000",
// If omitted, used "|" (no quotes) as default
"symbol": "|",
"font": "Noto Sans",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
// ‘smaller’ or ‘larger’
"font_size": "medium"
}
},
// Memory stats
"mem" : {
"enabled": true,
"show_swap": false,
"separator" : {
"left": {
"enabled": true,
"symbol": " |"
}
"right": {
"enabled": true
}
}
},
// Load Average
"la" : {
"enabled": true,
"separator" : {
"right": {
"enabled": true,
}
}
},
"net-if" : {
"enabled" : false,
// In html notation
"down_color" : "red",
"up_color" : "green",
"separator" : {
"right": {
"enabled": true,
}
},
"if" : [
{
// Name as it displayed on i3bar
"name" : "eth0",
// Directory containing net if status files
"dir" : "/sys/class/net/eth0"
}
]
},
// OpenVPN status. Note that directive status in openvpn.conf should point to
// state file and *update* its timestamp at least as frequent as mtime_threshold in seconds
"vpn": {
"enabled": false,
"statusfile" : "/tmp/openvpn-status.stat",
"mtime_threshold": 10,
// Color in html notation
"down_color" : "red",
"up_color" : "green",
"separator" : {
"right": {
"enabled": true,
}
},
// Also we can tcp-ping some service inside vpn network to ensure that connection is not stoned
"tcp_check" : {
"enabled": false,
"host": "somehost.tld",
"port": 443,
"timeout" : 3
}
},
// Simple sound volume indicator
"simple-volume-pa": {
"enabled": true,
"symbol": "VOL",
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of the relative sizes
// ‘smaller’ or ‘larger’. If omitted set to medium by default.
"font_size": "medium",
// If not defined - will be "true"
"right_click_cmd": ["pavucontrol"],
// Change volume step in %, if not configured it is 5
"step": 3,
// We'll change volume level with mouse wheel. Under X11 it is mapped to some buttons, typically 4 and 5 (z-axis).
// If omited, default value is 4
"wheel_up": 4,
// If omited, default value is 5
"wheel_down": 5,
// Maximum sound volume, can be over 100%, but sould not be :) Default value 100 if not set.
"max_volume_limit": 120,
"separator" : {
"right": {
"enabled": true,
}
}
},
// Just clock
"clock": {
"enabled" : true,
// Text color in html (actually, pango) notation
"color" : "#666666",
"font_size": "large",
"separator" : {
"right": {
"enabled": false,
}
},
"left_click" : {
"enabled" : false,
// cmd is array of command itself and its arguments
"cmd" : [ "orage" ]
},
"right_click" : {
"enabled" : false,
"cmd" : [ "true" ]
}
},
// Battery, useful for laptops
"battery": {
"enabled": false,
"charge_color": {
// colors in html notation
"full": "green",
"empty": "red",
"almost_full": "yellow",
"almost_empty": "orange"
},
"separator" : {
"right": {
"enabled": true,
}
}
},
// CPU Temperature monitor, shows average value among given sources
"cpu_temp": {
"enabled": false,
"separator" : {
"right": {
"enabled": true,
}
},
// Files in sysfs that contains cpu temperatures
"file": [
"/sys/class/hwmon/hwmon4/temp2_input",
"/sys/class/hwmon/hwmon4/temp3_input",
"/sys/class/hwmon/hwmon4/temp4_input",
"/sys/class/hwmon/hwmon4/temp5_input",
"/sys/class/hwmon/hwmon4/temp6_input",
"/sys/class/hwmon/hwmon4/temp7_input"
]
},
// Intended mainly for use with desktop notifications
// Because it inherits all env vars from i3, it can intercat with dbus and other
// such user session services.
"cron" : {
"enabled" : false,
"tasks" : [
{
// Time in crontab notation
"time" : "55 23 * * *",
"cmd" : [
"notify-send", "Sleeping Time!", "Take a nap."
]
},
{
// time in crontab format
"time" : "55 12 * * 2,4",
// commands as it should be invoked in bash script
"cmd" : [
"notify-send", "Pizza time!", "M-m-m, tasty!"
]
}
]
},
// Weather to display Application Buttons
"app_buttons": {
"enabled": true,
},
// Buttons - application launch "buttons"
"apps": [
{
"full_text" : "📂",
"name" : "thunar",
"cmd" : "thunar",
"instance": "thunar",
"class": "Thunar",
"color": "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 9
},
{
"full_text" : " ♬ ",
"name" : "deadbeef",
"cmd" : "deadbeef",
"instance" : "deadbeef",
"class" : "Deadbeef",
"color" : "#00aa33",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Term ",
"name" : "alacritty",
"cmd" : "alacritty",
"instance" : "Alacritty",
"class" : "Alacritty",
"color" : "#666666",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 9
},
{
"full_text" : " E ",
"name" : "edge",
"cmd" : "edge",
"instance" : "microsoft-edge",
"class" : "Microsoft-edge",
"color" : "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Ff ",
"name" : "firefox",
"cmd" : "firefox",
"instance" : "Navigator",
"class" : "Firefox",
"color" : "#ff5f1f",
"border": "#666666",
"border_active": "#3e78fd",
"separator_block_width": 2
},
{
"full_text" : " V ",
"name" : "vivaldi",
"cmd" : "Vivaldi",
"instance" : "vivaldi-stable",
"class" : "Vivaldi-stable",
"color" : "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " C ",
"name" : "chrome",
"cmd" : "chrome",
"instance" : "google-chrome",
"class" : "Google-chrome",
"color" : "#ffa500",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 9
},
{
"full_text" : " @ ",
"name" : "thunderbird",
"cmd" : "thunderbird",
"instance" : "Mail",
"class" : "Thunderbird",
"color" : "#006994",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " Tg ",
"name" : "telegram",
"cmd" : "Telegram",
"instance" : "Telegram",
"class" : "TelegramDesktop",
"color" : "#5a8850",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " D ",
"name" : "discord",
"cmd" : "Discord",
"instance" : "discord",
"class" : "discord",
"color" : "#5a8850",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " H ",
"name" : "hexchat",
"cmd" : "hexchat",
"instance" : "hexchat",
"class" : "Hexchat",
"color" : "#5a8850",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : "Psi",
"name" : "psi-plus",
"cmd" : "psi-plus",
"instance" : "psi-plus",
"class" : "Psi-plus",
"color" : "#5a8850",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 9
},
{
"full_text" : " T ",
"name" : "mousepad",
"cmd" : "mousepad",
"instance" : "mousepad",
"class" : "Mousepad",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " VSC ",
"name" : "code",
"cmd" : "code",
"instance" : "code",
"class" : "Code",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " G ",
"name" : "goland",
"cmd" : "goland",
"instance" : "goland",
"class" : "Goland",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 2
},
{
"full_text" : " ▢ ",
"name" : "ToolBox",
"cmd" : "/home/eleksir/.local/share/JetBrains/Toolbox/bin/jetbrains-toolbox",
"instance" : "JetBrains Toolbox",
"class" : "jetbrains-toolbox",
"border": "#666666",
"border_active": "#3e78fd",
"separator": false,
"separator_block_width": 9
},
{
"full_text" : " 🔑 ",
"name" : "keepassxc",
"cmd" : "kee",
"instance" : "keepassxc",
"class" : "KeePassXC",
"color" : "#7ec850",
"border" : "#666666",
"border_active" : "#3e78fd"
}
]
}

14
go.mod
View File

@@ -3,11 +3,11 @@ module github.com/eleksir/i3status-go
go 1.21
require (
github.com/adrg/xdg v0.4.0
github.com/adrg/xdg v0.5.0
github.com/distatus/battery v0.11.0
github.com/go-co-op/gocron/v2 v2.1.2
github.com/go-co-op/gocron/v2 v2.11.0
github.com/hjson/hjson-go v3.3.0+incompatible
github.com/mafik/pulseaudio v0.0.0-20200511091429-8449222912dd
github.com/mafik/pulseaudio v0.0.0-20240327130323-384e01075e6e
github.com/shirou/gopsutil v3.21.11+incompatible
go.i3wm.org/i3 v0.0.0-20190720062127-36e6ec85cc5a
)
@@ -16,11 +16,11 @@ require (
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
golang.org/x/sys v0.16.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/sys v0.25.0 // indirect
howett.net/plist v1.0.1 // indirect
)

45
go.sum
View File

@@ -4,60 +4,55 @@ github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distatus/battery v0.11.0 h1:KJk89gz90Iq/wJtbjjM9yUzBXV+ASV/EG2WOOL7N8lc=
github.com/distatus/battery v0.11.0/go.mod h1:KmVkE8A8hpIX4T78QRdMktYpEp35QfOL8A8dwZBxq2k=
github.com/go-co-op/gocron/v2 v2.1.2 h1:+6tTOA9aBaKXpDWExw07hYoGEBzT+4CkGSVAiJ7WSXs=
github.com/go-co-op/gocron/v2 v2.1.2/go.mod h1:0MfNAXEchzeSH1vtkZrTAcSMWqyL435kL6CA4b0bjrg=
github.com/go-co-op/gocron/v2 v2.11.0 h1:IOowNA6SzwdRFnD4/Ol3Kj6G2xKfsoiiGq2Jhhm9bvE=
github.com/go-co-op/gocron/v2 v2.11.0/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hjson/hjson-go v3.3.0+incompatible h1:Rqr+Ya+0aCJMjaE4s8E9YKvuJLuLVpEvz4ONum52vnI=
github.com/hjson/hjson-go v3.3.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/mafik/pulseaudio v0.0.0-20200511091429-8449222912dd h1:gn6oLpDCn3wY+1WfbbP0OwxXL+2eHi3mxF/DsNyPHUM=
github.com/mafik/pulseaudio v0.0.0-20200511091429-8449222912dd/go.mod h1:dlpd1fnLAhI6g9tM/aCobgN/Yka1/SkHrBTfAgDdb9Q=
github.com/mafik/pulseaudio v0.0.0-20240327130323-384e01075e6e h1:y6jINFpNNS+IEizD6s9j35aKVNRsfsoEKN8IStRDQm0=
github.com/mafik/pulseaudio v0.0.0-20240327130323-384e01075e6e/go.mod h1:dlpd1fnLAhI6g9tM/aCobgN/Yka1/SkHrBTfAgDdb9Q=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.i3wm.org/i3 v0.0.0-20190720062127-36e6ec85cc5a h1:yeQv6GWN8DsA2f3b+u1zhRIJg2HmsGYqXsd+W7ULr7Q=
go.i3wm.org/i3 v0.0.0-20190720062127-36e6ec85cc5a/go.mod h1:7w17+r1F28Yxb1pHu8SxARJo+RGvJCAGOEf+GLw+2aQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc h1:ZMCWScCvS2fUVFw8LOpxyUUW5qiviqr4Dg5NdjLeiLU=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=

View File

@@ -386,6 +386,14 @@
// Maximum sound volume, can be over 100%, but sould not be :) Default value 100 if not set.
"max_volume_limit": 120,
// PA has annoying feature - socket activation. Sound system must persist and be available to all users regardless
// of init or other things. They just fail to understand that. Or they fucked up pulseaudio just because they scary
// of security something of resposibility. Anyway this is grand disign flaw, but we still have to bear with it.
// This setting defines if pulseaudion will be run in manner that allows it to exit is other login detected (how
// they guess it - I do not know). In general case we do not want allow pa to exit and leave our session without
// audio.
"dont_exit_on_login": true,
// Re-define separator parameters for net-if block here.
"separator": {
"left": {

169
main.go
View File

@@ -19,10 +19,10 @@ type I3BarOutBlock struct {
Color string `json:"color,omitempty"`
Background string `json:"background,omitempty"`
Border string `json:"border,omitempty"`
BorderTop int `json:"border_top,omitempty"`
BorderRight int `json:"border_right,omitempty"`
BorderBottom int `json:"border_bottom,omitempty"`
BorderLeft int `json:"border_left,omitempty"`
BorderTop int `json:"border_top"`
BorderRight int `json:"border_right"`
BorderBottom int `json:"border_bottom"`
BorderLeft int `json:"border_left"`
// measured either in pixels or in characters, so either int or string, let's make it string :)
MinWidth string `json:"min_width,omitempty"`
Align string `json:"align,omitempty"`
@@ -36,6 +36,7 @@ type I3BarOutBlock struct {
// UpdateReady channel that "refreshes" i3bar (generates stdout json line).
var UpdateReady = make(chan bool)
var MsgChan = make(chan []I3BarOutBlock, 64)
//go:embed i3status-go-example.json
var EmbeddedDefaultConfig embed.FS
@@ -51,6 +52,48 @@ func main() {
Conf, err = readConf()
// TODO: Проставить дефолтные значения для глобальных переменных модулей.
Batt = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.SymbolFont,
Conf.Battery.SymbolFontSize,
Conf.Battery.Symbol,
)
Batt += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
Conf.Battery.Color,
Conf.Battery.Background,
Conf.Battery.Font,
Conf.Battery.FontSize,
)
SoundVolume = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>🔊</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.SymbolFont,
Conf.SimpleVolumePa.SymbolFontSize,
)
SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:0%%</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.Font,
Conf.SimpleVolumePa.FontSize,
)
Clock = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>Thu, 1 Jan 1970 1:00</span>",
Conf.Clock.Color,
Conf.Clock.Background,
Conf.Clock.Font,
Conf.Clock.FontSize,
)
if err != nil {
log.Panicln(err)
}
@@ -58,6 +101,8 @@ func main() {
go Spawner()
go ParseStdin()
go CleanZombies()
go SVPAHandler()
go PrintToI3bar()
if Conf.AppButtons.Enabled {
go UpdateI3WinList()
@@ -67,7 +112,10 @@ func main() {
go sigHandler()
signal.Notify(sigChan,
syscall.SIGUSR1,
syscall.SIGUSR2)
syscall.SIGUSR2,
syscall.SIGQUIT,
syscall.SIGTERM,
syscall.SIGINT)
// Populate memory stats
if Conf.Mem.Enabled {
@@ -138,9 +186,10 @@ func main() {
if num == 0 {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.AppButtons.Separator.Left.Color,
Conf.AppButtons.Separator.Left.Background,
Conf.AppButtons.Separator.Left.Font,
Conf.AppButtons.Separator.Left.FontSize,
Conf.AppButtons.Separator.Left.Symbol,
)
@@ -150,9 +199,10 @@ func main() {
if num == len(Conf.Apps) {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.AppButtons.Separator.Right.Color,
Conf.AppButtons.Separator.Right.Background,
Conf.AppButtons.Separator.Right.Font,
Conf.AppButtons.Separator.Right.FontSize,
Conf.AppButtons.Separator.Right.Symbol,
)
@@ -172,6 +222,11 @@ func main() {
b.Border = app.Border
}
b.BorderTop = 1
b.BorderRight = 1
b.BorderBottom = 1
b.BorderLeft = 1
j = append(j, b)
}
}
@@ -184,16 +239,19 @@ func main() {
if Conf.CPUTemp.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.CPUTemp.Separator.Left.Color,
Conf.CPUTemp.Separator.Left.Background,
Conf.CPUTemp.Separator.Left.Font,
Conf.CPUTemp.Separator.Left.FontSize,
Conf.CPUTemp.Separator.Left.Symbol,
)
}
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>CPU: %d°</span>",
"<span color='%s' background='%s' font='%s' size='%s'>CPU: %d°</span>",
Conf.CPUTemp.Color,
Conf.CPUTemp.Background,
Conf.CPUTemp.Font,
Conf.CPUTemp.FontSize,
CPUTemperature,
@@ -201,9 +259,10 @@ func main() {
if Conf.CPUTemp.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.CPUTemp.Separator.Right.Color,
Conf.CPUTemp.Separator.Right.Background,
Conf.CPUTemp.Separator.Right.Font,
Conf.CPUTemp.Separator.Right.FontSize,
Conf.CPUTemp.Separator.Right.Symbol,
)
@@ -223,9 +282,10 @@ func main() {
if Conf.Mem.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Mem.Separator.Left.Color,
Conf.Mem.Separator.Left.Background,
Conf.Mem.Separator.Left.Font,
Conf.Mem.Separator.Left.FontSize,
Conf.Mem.Separator.Left.Symbol,
)
@@ -233,7 +293,9 @@ func main() {
if Conf.Mem.ShowSwap {
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>M:%d%% SHM:%dM SW:%dM</span>",
"<span color='%s' background='%s' font='%s' size='%s'>M:%d%% SHM:%dM SW:%dM</span>",
Conf.Mem.Color,
Conf.Mem.Background,
Conf.Mem.Font,
Conf.Mem.FontSize,
Memory.Usedpct,
@@ -242,7 +304,9 @@ func main() {
)
} else {
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>M:%d%% SHM:%dM</span>",
"<span color='%s' background='%s' font='%s' size='%s'>M:%d%% SHM:%dM</span>",
Conf.Mem.Color,
Conf.Mem.Background,
Conf.Mem.Font,
Conf.Mem.FontSize,
Memory.Usedpct,
@@ -252,9 +316,10 @@ func main() {
if Conf.Mem.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Mem.Separator.Right.Color,
Conf.Mem.Separator.Right.Background,
Conf.Mem.Separator.Right.Font,
Conf.Mem.Separator.Right.FontSize,
Conf.Mem.Separator.Right.Symbol,
)
@@ -274,16 +339,19 @@ func main() {
if Conf.LA.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.LA.Separator.Left.Color,
Conf.LA.Separator.Left.Background,
Conf.LA.Separator.Left.Font,
Conf.LA.Separator.Left.FontSize,
Conf.LA.Separator.Left.Symbol,
)
}
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>LA:%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>LA:%s</span>",
Conf.LA.Color,
Conf.LA.Background,
Conf.LA.Font,
Conf.LA.FontSize,
La,
@@ -291,9 +359,10 @@ func main() {
if Conf.LA.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.LA.Separator.Right.Color,
Conf.LA.Separator.Right.Background,
Conf.LA.Separator.Right.Font,
Conf.LA.Separator.Right.FontSize,
Conf.LA.Separator.Right.Symbol,
)
@@ -313,16 +382,19 @@ func main() {
if Conf.NetIf.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.NetIf.Separator.Left.Color,
Conf.NetIf.Separator.Left.Background,
Conf.NetIf.Separator.Left.Font,
Conf.NetIf.Separator.Left.FontSize,
Conf.NetIf.Separator.Left.Symbol,
)
}
b.FullText += fmt.Sprintf(
"<span font='%s' size= '%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size= '%s'>%s</span>",
Conf.NetIf.Color,
Conf.NetIf.Background,
Conf.NetIf.Font,
Conf.NetIf.FontSize,
IfStatus,
@@ -330,9 +402,10 @@ func main() {
if Conf.NetIf.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.NetIf.Separator.Right.Color,
Conf.NetIf.Separator.Right.Background,
Conf.NetIf.Separator.Right.Font,
Conf.NetIf.Separator.Right.FontSize,
Conf.NetIf.Separator.Right.Symbol,
)
@@ -352,16 +425,19 @@ func main() {
if Conf.Vpn.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Vpn.Separator.Left.Color,
Conf.Vpn.Separator.Left.Background,
Conf.Vpn.Separator.Left.Font,
Conf.Vpn.Separator.Left.FontSize,
Conf.Vpn.Separator.Left.Symbol,
)
}
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Vpn.Color,
Conf.Vpn.Background,
Conf.Vpn.Font,
Conf.Vpn.FontSize,
VPNStatus,
@@ -369,9 +445,10 @@ func main() {
if Conf.Vpn.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Vpn.Separator.Right.Color,
Conf.Vpn.Separator.Right.Background,
Conf.Vpn.Separator.Right.Font,
Conf.Vpn.Separator.Right.FontSize,
Conf.Vpn.Separator.Right.Symbol,
)
@@ -391,9 +468,10 @@ func main() {
if Conf.Battery.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Battery.Separator.Left.Color,
Conf.Battery.Separator.Left.Background,
Conf.Battery.Separator.Left.Font,
Conf.Battery.Separator.Left.FontSize,
Conf.Battery.Separator.Left.Symbol,
)
@@ -403,9 +481,10 @@ func main() {
if Conf.Battery.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Battery.Separator.Right.Color,
Conf.Battery.Separator.Right.Background,
Conf.Battery.Separator.Right.Font,
Conf.Battery.Separator.Right.FontSize,
Conf.Battery.Separator.Right.Symbol,
)
@@ -426,9 +505,10 @@ func main() {
if Conf.SimpleVolumePa.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.SimpleVolumePa.Separator.Left.Color,
Conf.SimpleVolumePa.Separator.Left.Background,
Conf.SimpleVolumePa.Separator.Left.Font,
Conf.SimpleVolumePa.Separator.Left.FontSize,
Conf.SimpleVolumePa.Separator.Left.Symbol,
)
@@ -439,9 +519,10 @@ func main() {
if Conf.SimpleVolumePa.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.SimpleVolumePa.Separator.Right.Color,
Conf.SimpleVolumePa.Separator.Right.Background,
Conf.SimpleVolumePa.Separator.Right.Font,
Conf.SimpleVolumePa.Separator.Right.FontSize,
Conf.SimpleVolumePa.Separator.Right.Symbol,
)
@@ -462,16 +543,19 @@ func main() {
if Conf.Clock.Separator.Left.Enabled {
b.FullText = fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Clock.Separator.Left.Color,
Conf.Clock.Separator.Left.Background,
Conf.Clock.Separator.Left.Font,
Conf.Clock.Separator.Left.FontSize,
Conf.Clock.Separator.Left.Symbol,
)
}
b.FullText += fmt.Sprintf(
"<span font='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Clock.Color,
Conf.Clock.Background,
Conf.Clock.Font,
Conf.Clock.FontSize,
Clock,
@@ -479,9 +563,10 @@ func main() {
if Conf.Clock.Separator.Right.Enabled {
b.FullText += fmt.Sprintf(
"<span color='%s' background='%s' size='%s'>%s</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Clock.Separator.Right.Color,
Conf.Clock.Separator.Right.Background,
Conf.Clock.Separator.Right.Font,
Conf.Clock.Separator.Right.FontSize,
Conf.Clock.Separator.Right.Symbol,
)
@@ -494,23 +579,25 @@ func main() {
}
if PrintOutput && len(j) > 0 {
PrintToI3bar(j)
MsgChan <- j
}
}
}
}
// PrintToI3bar prints info to stdout according to ipc docs (https://i3wm.org/docs/i3bar-protocol.html)
func PrintToI3bar(message []I3BarOutBlock) {
// we do not need to html-encode output, json.Marshal does this forcefully, so invent our own Marshal
buf := new(bytes.Buffer)
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(message)
func PrintToI3bar() {
for message := range MsgChan {
// we do not need to html-encode output, json.Marshal does this forcefully, so invent our own Marshal
buf := new(bytes.Buffer)
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(message)
if err != nil {
log.Printf("Unable to json-encode message, %s\n", err)
if err != nil {
log.Printf("Unable to json-encode message, %s\n", err)
}
fmt.Println(strings.TrimSuffix(buf.String(), "\n") + ",")
}
fmt.Println(strings.TrimSuffix(buf.String(), "\n") + ",")
}

View File

@@ -1,9 +1,11 @@
package main
import (
"errors"
"fmt"
"log"
"os/exec"
"time"
p "github.com/mafik/pulseaudio"
)
@@ -11,6 +13,10 @@ import (
var SoundVolume = "🔊:0%"
var pa *p.Client
var SVPAHandlerChan = make(chan ClickEvent, 256)
// TODO: https://twin.sh/articles/44/add-a-timeout-to-any-function-in-go timeout pulseaudio calls
// UpdateVolumeInfo updates info about current Sound Volume.
func UpdateVolumeInfo() {
var err error
@@ -36,10 +42,18 @@ func UpdateVolumeInfo() {
}
SoundVolume = fmt.Sprintf(
"<span font='%s' size='%s'>%s</span><span font='%s' size='%s'>:%d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.SymbolFont,
Conf.SimpleVolumePa.SymbolFontSize,
Conf.SimpleVolumePa.Symbol,
)
SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.Font,
Conf.SimpleVolumePa.FontSize,
int64(vol*100),
@@ -57,7 +71,7 @@ func UpdateVolumeInfo() {
return
}
// Rake update events
// Rake update events.
for range pulseUpdate {
vol, err = pa.Volume()
@@ -68,10 +82,18 @@ func UpdateVolumeInfo() {
}
SoundVolume = fmt.Sprintf(
"<span font='%s' size='%s'>%s</span><span font='%s' size='%s'>:%d%%</span>",
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.SymbolFont,
Conf.SimpleVolumePa.SymbolFontSize,
Conf.SimpleVolumePa.Symbol,
)
SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
Conf.SimpleVolumePa.Font,
Conf.SimpleVolumePa.FontSize,
int64(vol*100),
@@ -99,10 +121,49 @@ func PaReinit() error {
cmd := exec.Command("pulseaudio", "--check")
if err := cmd.Run(); err == nil {
return fmt.Errorf("pulseaudio is already running, but we have troubles contacting it: %w", err)
log.Printf("pulseaudio already running, but seems not responding, try gracefully kill it")
cmd = exec.Command("pulseaudio", "--kill")
if err := cmd.Run(); err != nil {
return fmt.Errorf("unable to kill pulseaudio: %w", err)
}
cnt := 0
for {
cmd := exec.Command("pulseaudio", "--check")
// PA not running. Breakout of loop.
if err := cmd.Run(); err != nil {
break
}
if cnt >= 5 {
return errors.New("timeout waiting pulseaudio to exit") //nolint: goerr113
}
log.Print("Waiting for pulseaudio to exit")
cnt++
time.Sleep(300 * time.Millisecond)
}
}
cmd = exec.Command("pulseaudio", "--start")
// PA has annoying feature: socket activation. Sound system must be persistent and available to all users regardless
// of init or other things. They just fail to understand that. Or they fucked up pulseaudio just because they scary
// of security something responsibility. Anyway this is grand design flaw, but we still have to bear with it.
// This setting defines if pulseaudio will be run in manner that allows it to exit is other login detected (how
// they guess it - I do not know). In general case we do not want to allow pa to exit and leave our session without
// audio.
if Conf.SimpleVolumePa.DontExitOnLogin {
// Do not exit on any kind of login/logout events.
cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start")
} else {
// Exit immediately on logout(?).
cmd = exec.Command("pulseaudio", "--exit-idle-time=0", "--start")
}
if err := cmd.Run(); err != nil {
return fmt.Errorf("unable to initialize pulseaudio server instance: %w", err)
@@ -116,3 +177,51 @@ func PaReinit() error {
return err
}
func SVPAHandler() {
for e := range SVPAHandlerChan {
if e.Button == 3 {
RunChan <- Conf.SimpleVolumePa.RightClickCmd
continue
}
vol, err := pa.Volume()
if err != nil {
if err := PaReinit(); err != nil {
log.Printf("Unable to get pulseaudio volume: %s", err)
} else {
vol, err = pa.Volume()
if err != nil {
log.Printf("Unable to get volume pulseaudio server behaves weirdly: %s", err)
}
}
}
switch e.Button {
case Conf.SimpleVolumePa.WheelUp:
vol += float32(Conf.SimpleVolumePa.Step) / 100
if vol > (float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100) {
vol = float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100
}
if err := pa.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err)
}
case Conf.SimpleVolumePa.WheelDown:
vol -= float32(Conf.SimpleVolumePa.Step) / 100
if vol < 0 {
vol = 0
}
if err := pa.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err)
}
}
}
}

View File

@@ -25,6 +25,9 @@ func sigHandler() {
UpdateReady <- true
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
os.Exit(0)
// We have signal that we're not interested in, so make a new loop iteration.
default:
continue

View File

@@ -11,7 +11,7 @@ import (
// RunChan to this channel we send command and its argv to execute as separate process.
var RunChan = make(chan []string, 128)
// Spawn forks and execs given program, and also detaches form its control tty.
// Spawner forks and execs given program, and also detaches form its control tty.
func Spawner() {
for prg := range RunChan {
devnullR, _ := os.Open(os.DevNull)

View File

@@ -95,49 +95,7 @@ func ParseStdin() {
if e.Name == "simple-volume-pa" {
if Conf.SimpleVolumePa.Enabled {
if e.Button == 3 {
RunChan <- Conf.SimpleVolumePa.RightClickCmd
continue
}
vol, err := pa.Volume()
if err != nil {
if err := PaReinit(); err != nil {
log.Printf("Unable to get pulseaudio volume: %s", err)
} else {
vol, err = pa.Volume()
if err != nil {
log.Printf("Unable to get volume pulseaudio server behaves weirdly: %s", err)
}
}
}
switch e.Button {
case Conf.SimpleVolumePa.WheelUp:
vol += float32(Conf.SimpleVolumePa.Step) / 100
if vol > (float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100) {
vol = float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100
}
if err := pa.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err)
}
case Conf.SimpleVolumePa.WheelDown:
vol -= float32(Conf.SimpleVolumePa.Step) / 100
if vol < 0 {
vol = 0
}
if err := pa.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err)
}
}
SVPAHandlerChan <- e
}
continue

24
vendor/github.com/adrg/xdg/README.md generated vendored
View File

@@ -7,8 +7,8 @@
<h4 align="center">Go implementation of the XDG Base Directory Specification and XDG user directories.</h4>
<p align="center">
<a href="https://github.com/adrg/xdg/actions?query=workflow%3ACI">
<img alt="Build status" src="https://github.com/adrg/xdg/workflows/CI/badge.svg">
<a href="https://github.com/adrg/xdg/actions/workflows/tests.yml">
<img alt="Tests status" src="https://github.com/adrg/xdg/actions/workflows/tests.yml/badge.svg">
</a>
<a href="https://app.codecov.io/gh/adrg/xdg">
<img alt="Code coverage" src="https://codecov.io/gh/adrg/xdg/branch/master/graphs/badge.svg?branch=master">
@@ -58,7 +58,7 @@ See usage [examples](#usage) below. Full documentation can be found at https://p
The package defines sensible defaults for XDG variables which are empty or not
present in the environment.
- On Unix-like operating systems, XDG environment variables are tipically defined.
- On Unix-like operating systems, XDG environment variables are typically defined.
Appropriate default locations are used for the environment variables which are not set.
- On Windows, XDG environment variables are usually not set. If that is the case,
the package relies on the appropriate [Known Folders](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
@@ -100,6 +100,17 @@ Sensible fallback locations are used for the folders which are not set.
### XDG user directories
XDG user directories environment variables are usually **not** set on most
operating systems. However, if they are present in the environment, they take
precedence. Appropriate fallback locations are used for the environment
variables which are not set.
- On Unix-like operating systems (except macOS and Plan 9), the package reads the [user-dirs.dirs](https://man.archlinux.org/man/user-dirs.dirs.5.en) config file.
- On Windows, the package uses the appropriate [Known Folders](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
Lastly, default locations are used for any user directories which are not set,
as shown in the following tables.
<details open>
<summary><strong>Unix-like operating systems</strong></summary>
<br/>
@@ -156,7 +167,7 @@ Sensible fallback locations are used for the folders which are not set.
| :-----------------------------------------------------------: | :--------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: |
| <kbd><b>Home</b></kbd> | <kbd>Profile</kbd> | <kbd>%USERPROFILE%</kbd> |
| <kbd><b>Applications</b></kbd> | <kbd>Programs</kbd><br/><kbd>CommonPrograms</kbd> | <kbd>%APPDATA%\Microsoft\Windows\Start&nbsp;Menu\Programs</kbd><br/><kbd>%ProgramData%\Microsoft\Windows\Start&nbsp;Menu\Programs</kbd> |
| <kbd><b>Fonts</b></kbd> | <kbd>Fonts</kbd><br/><kbd>-</kbd> | <kbd>%SystemRoot%\Fonts</kbd><br/><kbd>%LOCALAPPDATA%\Microsoft\Windows\Fonts</kbd> |
| <kbd><b>Fonts</b></kbd> | <kbd>Fonts</kbd> | <kbd>%SystemRoot%\Fonts</kbd><br/><kbd>%LOCALAPPDATA%\Microsoft\Windows\Fonts</kbd> |
</details>
@@ -263,7 +274,10 @@ See [CONTRIBUTING.MD](CONTRIBUTING.md).
[gabriel-vasile](https://github.com/gabriel-vasile),
[KalleDK](https://github.com/KalleDK),
[nvkv](https://github.com/nvkv),
[djdv](https://github.com/djdv).
[djdv](https://github.com/djdv),
[rrjjvv](https://github.com/rrjjvv),
[GreyXor](https://github.com/GreyXor),
[Rican7](https://github.com/Rican7).
## References

View File

@@ -8,18 +8,17 @@ import (
)
// Unique eliminates the duplicate paths from the provided slice and returns
// the result. The items in the output slice are in the order in which they
// occur in the input slice. If a `home` location is provided, the paths are
// expanded using the `ExpandHome` function.
func Unique(paths []string, home string) []string {
// the result. The paths are expanded using the `ExpandHome` function and only
// absolute paths are kept. The items in the output slice are in the order in
// which they occur in the input slice.
func Unique(paths []string) []string {
var (
uniq []string
registry = map[string]struct{}{}
)
for _, p := range paths {
p = ExpandHome(p, home)
if p != "" && filepath.IsAbs(p) {
if p = ExpandHome(p); p != "" && filepath.IsAbs(p) {
if _, ok := registry[p]; ok {
continue
}
@@ -32,6 +31,18 @@ func Unique(paths []string, home string) []string {
return uniq
}
// First returns the first absolute path from the provided slice.
// The paths in the input slice are expanded using the `ExpandHome` function.
func First(paths []string) string {
for _, p := range paths {
if p = ExpandHome(p); p != "" && filepath.IsAbs(p) {
return p
}
}
return ""
}
// Create returns a suitable location relative to which the file with the
// specified `name` can be written. The first path from the provided `paths`
// slice which is successfully created (or already exists) is used as a base
@@ -40,7 +51,8 @@ func Unique(paths []string, home string) []string {
// it can also contain a set of parent directories, which will be created
// relative to the selected parent path.
func Create(name string, paths []string) (string, error) {
var searchedPaths []string
searchedPaths := make([]string, 0, len(paths))
for _, p := range paths {
p = filepath.Join(p, name)
@@ -48,7 +60,7 @@ func Create(name string, paths []string) (string, error) {
if Exists(dir) {
return p, nil
}
if err := os.MkdirAll(dir, os.ModeDir|0700); err == nil {
if err := os.MkdirAll(dir, os.ModeDir|0o700); err == nil {
return p, nil
}
@@ -63,7 +75,8 @@ func Create(name string, paths []string) (string, error) {
// slice of `paths`. The `name` parameter must contain the name of the file,
// but it can also contain a set of parent directories.
func Search(name string, paths []string) (string, error) {
var searchedPaths []string
searchedPaths := make([]string, 0, len(paths))
for _, p := range paths {
p = filepath.Join(p, name)
if Exists(p) {
@@ -76,3 +89,29 @@ func Search(name string, paths []string) (string, error) {
return "", fmt.Errorf("could not locate `%s` in any of the following paths: %s",
filepath.Base(name), strings.Join(searchedPaths, ", "))
}
// EnvPath returns the value of the environment variable with the specified
// `name` if it is an absolute path, or the first absolute fallback path.
// All paths are expanded using the `ExpandHome` function.
func EnvPath(name string, fallbackPaths ...string) string {
dir := ExpandHome(os.Getenv(name))
if dir != "" && filepath.IsAbs(dir) {
return dir
}
return First(fallbackPaths)
}
// EnvPathList reads the value of the environment variable with the specified
// `name` and attempts to extract a list of absolute paths from it. If there
// are none, a list of absolute fallback paths is returned instead. Duplicate
// paths are removed from the returned slice. All paths are expanded using the
// `ExpandHome` function.
func EnvPathList(name string, fallbackPaths ...string) []string {
dirs := Unique(filepath.SplitList(os.Getenv(name)))
if len(dirs) != 0 {
return dirs
}
return Unique(fallbackPaths)
}

View File

@@ -1,20 +1,31 @@
package pathutil
import (
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
)
// UserHomeDir returns the home directory of the current user.
func UserHomeDir() string {
if home := os.Getenv("home"); home != "" {
return home
}
return "/"
}
// Exists returns true if the specified path exists.
func Exists(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
return err == nil || errors.Is(err, fs.ErrExist)
}
// ExpandHome substitutes `~` and `$home` at the start of the specified
// `path` using the provided `home` location.
func ExpandHome(path, home string) string {
// ExpandHome substitutes `~` and `$home` at the start of the specified `path`.
func ExpandHome(path string) string {
home := UserHomeDir()
if path == "" || home == "" {
return path
}

View File

@@ -1,23 +1,33 @@
//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || nacl || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd js,wasm nacl linux netbsd openbsd solaris
package pathutil
import (
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
)
// UserHomeDir returns the home directory of the current user.
func UserHomeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
return "/"
}
// Exists returns true if the specified path exists.
func Exists(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
return err == nil || errors.Is(err, fs.ErrExist)
}
// ExpandHome substitutes `~` and `$HOME` at the start of the specified
// `path` using the provided `home` location.
func ExpandHome(path, home string) string {
// ExpandHome substitutes `~` and `$HOME` at the start of the specified `path`.
func ExpandHome(path string) string {
home := UserHomeDir()
if path == "" || home == "" {
return path
}

View File

@@ -1,6 +1,8 @@
package pathutil
import (
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
@@ -8,6 +10,11 @@ import (
"golang.org/x/sys/windows"
)
// UserHomeDir returns the home directory of the current user.
func UserHomeDir() string {
return KnownFolder(windows.FOLDERID_Profile, []string{"USERPROFILE"}, nil)
}
// Exists returns true if the specified path exists.
func Exists(path string) bool {
fi, err := os.Lstat(path)
@@ -15,12 +22,12 @@ func Exists(path string) bool {
_, err = filepath.EvalSymlinks(path)
}
return err == nil || os.IsExist(err)
return err == nil || errors.Is(err, fs.ErrExist)
}
// ExpandHome substitutes `%USERPROFILE%` at the start of the specified
// `path` using the provided `home` location.
func ExpandHome(path, home string) string {
// ExpandHome substitutes `%USERPROFILE%` at the start of the specified `path`.
func ExpandHome(path string) string {
home := UserHomeDir()
if path == "" || home == "" {
return path
}

View File

@@ -0,0 +1,82 @@
//go:build aix || dragonfly || freebsd || (js && wasm) || nacl || linux || netbsd || openbsd || solaris
package userdirs
import (
"bufio"
"io"
"os"
"strings"
"github.com/adrg/xdg/internal/pathutil"
)
// ParseConfigFile parses the user directories config file at the
// specified location.
func ParseConfigFile(name string) (*Directories, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
return ParseConfig(f)
}
// ParseConfig parses the user directories config file contained in
// the provided reader.
func ParseConfig(r io.Reader) (*Directories, error) {
dirs := &Directories{}
fieldsMap := map[string]*string{
EnvDesktopDir: &dirs.Desktop,
EnvDownloadDir: &dirs.Download,
EnvDocumentsDir: &dirs.Documents,
EnvMusicDir: &dirs.Music,
EnvPicturesDir: &dirs.Pictures,
EnvVideosDir: &dirs.Videos,
EnvTemplatesDir: &dirs.Templates,
EnvPublicShareDir: &dirs.PublicShare,
}
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) == 0 || line[0] == '#' {
continue
}
if !strings.HasPrefix(line, "XDG_") {
continue
}
parts := strings.Split(line, "=")
if len(parts) < 2 {
continue
}
// Parse key.
field, ok := fieldsMap[strings.TrimSpace(parts[0])]
if !ok {
continue
}
// Parse value.
runes := []rune(strings.TrimSpace(parts[1]))
lenRunes := len(runes)
if lenRunes <= 2 || runes[0] != '"' {
continue
}
for i := 1; i < lenRunes; i++ {
if runes[i] == '"' {
*field = pathutil.ExpandHome(string(runes[1:i]))
break
}
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return dirs, nil
}

View File

@@ -1,19 +1,19 @@
package xdg
package userdirs
// XDG user directories environment variables.
const (
envDesktopDir = "XDG_DESKTOP_DIR"
envDownloadDir = "XDG_DOWNLOAD_DIR"
envDocumentsDir = "XDG_DOCUMENTS_DIR"
envMusicDir = "XDG_MUSIC_DIR"
envPicturesDir = "XDG_PICTURES_DIR"
envVideosDir = "XDG_VIDEOS_DIR"
envTemplatesDir = "XDG_TEMPLATES_DIR"
envPublicShareDir = "XDG_PUBLICSHARE_DIR"
EnvDesktopDir = "XDG_DESKTOP_DIR"
EnvDownloadDir = "XDG_DOWNLOAD_DIR"
EnvDocumentsDir = "XDG_DOCUMENTS_DIR"
EnvMusicDir = "XDG_MUSIC_DIR"
EnvPicturesDir = "XDG_PICTURES_DIR"
EnvVideosDir = "XDG_VIDEOS_DIR"
EnvTemplatesDir = "XDG_TEMPLATES_DIR"
EnvPublicShareDir = "XDG_PUBLICSHARE_DIR"
)
// UserDirectories defines the locations of well known user directories.
type UserDirectories struct {
// Directories defines the locations of well known user directories.
type Directories struct {
// Desktop defines the location of the user's desktop directory.
Desktop string

View File

@@ -1,18 +1,12 @@
package xdg
import (
"os"
"path/filepath"
"github.com/adrg/xdg/internal/pathutil"
"github.com/adrg/xdg/internal/userdirs"
)
func homeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
return "/"
}
func initDirs(home string) {
initBaseDirs(home)
initUserDirs(home)
@@ -23,17 +17,17 @@ func initBaseDirs(home string) {
rootAppSupport := "/Library/Application Support"
// Initialize standard directories.
baseDirs.dataHome = xdgPath(envDataHome, homeAppSupport)
baseDirs.data = xdgPaths(envDataDirs, rootAppSupport)
baseDirs.configHome = xdgPath(envConfigHome, homeAppSupport)
baseDirs.config = xdgPaths(envConfigDirs,
baseDirs.dataHome = pathutil.EnvPath(envDataHome, homeAppSupport)
baseDirs.data = pathutil.EnvPathList(envDataDirs, rootAppSupport)
baseDirs.configHome = pathutil.EnvPath(envConfigHome, homeAppSupport)
baseDirs.config = pathutil.EnvPathList(envConfigDirs,
filepath.Join(home, "Library", "Preferences"),
rootAppSupport,
"/Library/Preferences",
)
baseDirs.stateHome = xdgPath(envStateHome, homeAppSupport)
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(home, "Library", "Caches"))
baseDirs.runtime = xdgPath(envRuntimeDir, homeAppSupport)
baseDirs.stateHome = pathutil.EnvPath(envStateHome, homeAppSupport)
baseDirs.cacheHome = pathutil.EnvPath(envCacheHome, filepath.Join(home, "Library", "Caches"))
baseDirs.runtime = pathutil.EnvPath(envRuntimeDir, homeAppSupport)
// Initialize non-standard directories.
baseDirs.applications = []string{
@@ -49,12 +43,12 @@ func initBaseDirs(home string) {
}
func initUserDirs(home string) {
UserDirs.Desktop = xdgPath(envDesktopDir, filepath.Join(home, "Desktop"))
UserDirs.Download = xdgPath(envDownloadDir, filepath.Join(home, "Downloads"))
UserDirs.Documents = xdgPath(envDocumentsDir, filepath.Join(home, "Documents"))
UserDirs.Music = xdgPath(envMusicDir, filepath.Join(home, "Music"))
UserDirs.Pictures = xdgPath(envPicturesDir, filepath.Join(home, "Pictures"))
UserDirs.Videos = xdgPath(envVideosDir, filepath.Join(home, "Movies"))
UserDirs.Templates = xdgPath(envTemplatesDir, filepath.Join(home, "Templates"))
UserDirs.PublicShare = xdgPath(envPublicShareDir, filepath.Join(home, "Public"))
UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, filepath.Join(home, "Desktop"))
UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, filepath.Join(home, "Downloads"))
UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, filepath.Join(home, "Documents"))
UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, filepath.Join(home, "Music"))
UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, filepath.Join(home, "Pictures"))
UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, filepath.Join(home, "Movies"))
UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, filepath.Join(home, "Templates"))
UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, filepath.Join(home, "Public"))
}

View File

@@ -1,18 +1,12 @@
package xdg
import (
"os"
"path/filepath"
"github.com/adrg/xdg/internal/pathutil"
"github.com/adrg/xdg/internal/userdirs"
)
func homeDir() string {
if home := os.Getenv("home"); home != "" {
return home
}
return "/"
}
func initDirs(home string) {
initBaseDirs(home)
initUserDirs(home)
@@ -23,13 +17,13 @@ func initBaseDirs(home string) {
rootLibDir := "/lib"
// Initialize standard directories.
baseDirs.dataHome = xdgPath(envDataHome, homeLibDir)
baseDirs.data = xdgPaths(envDataDirs, rootLibDir)
baseDirs.configHome = xdgPath(envConfigHome, homeLibDir)
baseDirs.config = xdgPaths(envConfigDirs, rootLibDir)
baseDirs.stateHome = xdgPath(envStateHome, filepath.Join(homeLibDir, "state"))
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(homeLibDir, "cache"))
baseDirs.runtime = xdgPath(envRuntimeDir, "/tmp")
baseDirs.dataHome = pathutil.EnvPath(envDataHome, homeLibDir)
baseDirs.data = pathutil.EnvPathList(envDataDirs, rootLibDir)
baseDirs.configHome = pathutil.EnvPath(envConfigHome, homeLibDir)
baseDirs.config = pathutil.EnvPathList(envConfigDirs, rootLibDir)
baseDirs.stateHome = pathutil.EnvPath(envStateHome, filepath.Join(homeLibDir, "state"))
baseDirs.cacheHome = pathutil.EnvPath(envCacheHome, filepath.Join(homeLibDir, "cache"))
baseDirs.runtime = pathutil.EnvPath(envRuntimeDir, "/tmp")
// Initialize non-standard directories.
baseDirs.applications = []string{
@@ -44,12 +38,12 @@ func initBaseDirs(home string) {
}
func initUserDirs(home string) {
UserDirs.Desktop = xdgPath(envDesktopDir, filepath.Join(home, "desktop"))
UserDirs.Download = xdgPath(envDownloadDir, filepath.Join(home, "downloads"))
UserDirs.Documents = xdgPath(envDocumentsDir, filepath.Join(home, "documents"))
UserDirs.Music = xdgPath(envMusicDir, filepath.Join(home, "music"))
UserDirs.Pictures = xdgPath(envPicturesDir, filepath.Join(home, "pictures"))
UserDirs.Videos = xdgPath(envVideosDir, filepath.Join(home, "videos"))
UserDirs.Templates = xdgPath(envTemplatesDir, filepath.Join(home, "templates"))
UserDirs.PublicShare = xdgPath(envPublicShareDir, filepath.Join(home, "public"))
UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, filepath.Join(home, "desktop"))
UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, filepath.Join(home, "downloads"))
UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, filepath.Join(home, "documents"))
UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, filepath.Join(home, "music"))
UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, filepath.Join(home, "pictures"))
UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, filepath.Join(home, "videos"))
UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, filepath.Join(home, "templates"))
UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, filepath.Join(home, "public"))
}

View File

@@ -1,5 +1,4 @@
//go:build aix || dragonfly || freebsd || (js && wasm) || nacl || linux || netbsd || openbsd || solaris
// +build aix dragonfly freebsd js,wasm nacl linux netbsd openbsd solaris
package xdg
@@ -9,30 +8,23 @@ import (
"strconv"
"github.com/adrg/xdg/internal/pathutil"
"github.com/adrg/xdg/internal/userdirs"
)
func homeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
return "/"
}
func initDirs(home string) {
initBaseDirs(home)
initUserDirs(home)
initUserDirs(home, baseDirs.configHome)
}
func initBaseDirs(home string) {
// Initialize standard directories.
baseDirs.dataHome = xdgPath(envDataHome, filepath.Join(home, ".local", "share"))
baseDirs.data = xdgPaths(envDataDirs, "/usr/local/share", "/usr/share")
baseDirs.configHome = xdgPath(envConfigHome, filepath.Join(home, ".config"))
baseDirs.config = xdgPaths(envConfigDirs, "/etc/xdg")
baseDirs.stateHome = xdgPath(envStateHome, filepath.Join(home, ".local", "state"))
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(home, ".cache"))
baseDirs.runtime = xdgPath(envRuntimeDir, filepath.Join("/run/user", strconv.Itoa(os.Getuid())))
baseDirs.dataHome = pathutil.EnvPath(envDataHome, filepath.Join(home, ".local", "share"))
baseDirs.data = pathutil.EnvPathList(envDataDirs, "/usr/local/share", "/usr/share")
baseDirs.configHome = pathutil.EnvPath(envConfigHome, filepath.Join(home, ".config"))
baseDirs.config = pathutil.EnvPathList(envConfigDirs, "/etc/xdg")
baseDirs.stateHome = pathutil.EnvPath(envStateHome, filepath.Join(home, ".local", "state"))
baseDirs.cacheHome = pathutil.EnvPath(envCacheHome, filepath.Join(home, ".cache"))
baseDirs.runtime = pathutil.EnvPath(envRuntimeDir, filepath.Join("/run/user", strconv.Itoa(os.Getuid())))
// Initialize non-standard directories.
appDirs := []string{
@@ -55,17 +47,22 @@ func initBaseDirs(home string) {
fontDirs = append(fontDirs, filepath.Join(dir, "fonts"))
}
baseDirs.applications = pathutil.Unique(appDirs, Home)
baseDirs.fonts = pathutil.Unique(fontDirs, Home)
baseDirs.applications = pathutil.Unique(appDirs)
baseDirs.fonts = pathutil.Unique(fontDirs)
}
func initUserDirs(home string) {
UserDirs.Desktop = xdgPath(envDesktopDir, filepath.Join(home, "Desktop"))
UserDirs.Download = xdgPath(envDownloadDir, filepath.Join(home, "Downloads"))
UserDirs.Documents = xdgPath(envDocumentsDir, filepath.Join(home, "Documents"))
UserDirs.Music = xdgPath(envMusicDir, filepath.Join(home, "Music"))
UserDirs.Pictures = xdgPath(envPicturesDir, filepath.Join(home, "Pictures"))
UserDirs.Videos = xdgPath(envVideosDir, filepath.Join(home, "Videos"))
UserDirs.Templates = xdgPath(envTemplatesDir, filepath.Join(home, "Templates"))
UserDirs.PublicShare = xdgPath(envPublicShareDir, filepath.Join(home, "Public"))
func initUserDirs(home, configHome string) {
dirs, err := userdirs.ParseConfigFile(filepath.Join(configHome, "user-dirs.dirs"))
if err != nil {
dirs = &UserDirectories{}
}
UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, dirs.Desktop, filepath.Join(home, "Desktop"))
UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, dirs.Download, filepath.Join(home, "Downloads"))
UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, dirs.Documents, filepath.Join(home, "Documents"))
UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, dirs.Music, filepath.Join(home, "Music"))
UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, dirs.Pictures, filepath.Join(home, "Pictures"))
UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, dirs.Videos, filepath.Join(home, "Videos"))
UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, dirs.Templates, filepath.Join(home, "Templates"))
UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, dirs.PublicShare, filepath.Join(home, "Public"))
}

View File

@@ -4,17 +4,10 @@ import (
"path/filepath"
"github.com/adrg/xdg/internal/pathutil"
"github.com/adrg/xdg/internal/userdirs"
"golang.org/x/sys/windows"
)
func homeDir() string {
return pathutil.KnownFolder(
windows.FOLDERID_Profile,
[]string{"USERPROFILE"},
nil,
)
}
func initDirs(home string) {
kf := initKnownFolders(home)
initBaseDirs(home, kf)
@@ -23,13 +16,13 @@ func initDirs(home string) {
func initBaseDirs(home string, kf *knownFolders) {
// Initialize standard directories.
baseDirs.dataHome = xdgPath(envDataHome, kf.localAppData)
baseDirs.data = xdgPaths(envDataDirs, kf.roamingAppData, kf.programData)
baseDirs.configHome = xdgPath(envConfigHome, kf.localAppData)
baseDirs.config = xdgPaths(envConfigDirs, kf.programData, kf.roamingAppData)
baseDirs.stateHome = xdgPath(envStateHome, kf.localAppData)
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(kf.localAppData, "cache"))
baseDirs.runtime = xdgPath(envRuntimeDir, kf.localAppData)
baseDirs.dataHome = pathutil.EnvPath(envDataHome, kf.localAppData)
baseDirs.data = pathutil.EnvPathList(envDataDirs, kf.roamingAppData, kf.programData)
baseDirs.configHome = pathutil.EnvPath(envConfigHome, kf.localAppData)
baseDirs.config = pathutil.EnvPathList(envConfigDirs, kf.programData, kf.roamingAppData)
baseDirs.stateHome = pathutil.EnvPath(envStateHome, kf.localAppData)
baseDirs.cacheHome = pathutil.EnvPath(envCacheHome, filepath.Join(kf.localAppData, "cache"))
baseDirs.runtime = pathutil.EnvPath(envRuntimeDir, kf.localAppData)
// Initialize non-standard directories.
baseDirs.applications = []string{
@@ -43,14 +36,14 @@ func initBaseDirs(home string, kf *knownFolders) {
}
func initUserDirs(home string, kf *knownFolders) {
UserDirs.Desktop = xdgPath(envDesktopDir, kf.desktop)
UserDirs.Download = xdgPath(envDownloadDir, kf.downloads)
UserDirs.Documents = xdgPath(envDocumentsDir, kf.documents)
UserDirs.Music = xdgPath(envMusicDir, kf.music)
UserDirs.Pictures = xdgPath(envPicturesDir, kf.pictures)
UserDirs.Videos = xdgPath(envVideosDir, kf.videos)
UserDirs.Templates = xdgPath(envTemplatesDir, kf.templates)
UserDirs.PublicShare = xdgPath(envPublicShareDir, kf.public)
UserDirs.Desktop = pathutil.EnvPath(userdirs.EnvDesktopDir, kf.desktop)
UserDirs.Download = pathutil.EnvPath(userdirs.EnvDownloadDir, kf.downloads)
UserDirs.Documents = pathutil.EnvPath(userdirs.EnvDocumentsDir, kf.documents)
UserDirs.Music = pathutil.EnvPath(userdirs.EnvMusicDir, kf.music)
UserDirs.Pictures = pathutil.EnvPath(userdirs.EnvPicturesDir, kf.pictures)
UserDirs.Videos = pathutil.EnvPath(userdirs.EnvVideosDir, kf.videos)
UserDirs.Templates = pathutil.EnvPath(userdirs.EnvTemplatesDir, kf.templates)
UserDirs.PublicShare = pathutil.EnvPath(userdirs.EnvPublicShareDir, kf.public)
}
type knownFolders struct {

29
vendor/github.com/adrg/xdg/xdg.go generated vendored
View File

@@ -1,12 +1,13 @@
package xdg
import (
"os"
"path/filepath"
"github.com/adrg/xdg/internal/pathutil"
"github.com/adrg/xdg/internal/userdirs"
)
// UserDirectories defines the locations of well known user directories.
type UserDirectories = userdirs.Directories
var (
// Home contains the path of the user's home directory.
Home string
@@ -29,7 +30,7 @@ var (
// ConfigHome defines the base directory relative to which user-specific
// configuration files should be written. This directory is defined by
// the $XDG_CONFIG_HOME environment variable. If the variable is not
// the $XDG_CONFIG_HOME environment variable. If the variable is
// not set, a default equal to $HOME/.config should be used.
ConfigHome string
@@ -88,7 +89,7 @@ func init() {
// in the environment.
func Reload() {
// Initialize home directory.
Home = homeDir()
Home = pathutil.UserHomeDir()
// Initialize base and user directories.
initDirs(Home)
@@ -198,21 +199,3 @@ func SearchCacheFile(relPath string) (string, error) {
func SearchRuntimeFile(relPath string) (string, error) {
return baseDirs.searchRuntimeFile(relPath)
}
func xdgPath(name, defaultPath string) string {
dir := pathutil.ExpandHome(os.Getenv(name), Home)
if dir != "" && filepath.IsAbs(dir) {
return dir
}
return defaultPath
}
func xdgPaths(name string, defaultPaths ...string) []string {
dirs := pathutil.Unique(filepath.SplitList(os.Getenv(name)), Home)
if len(dirs) != 0 {
return dirs
}
return pathutil.Unique(defaultPaths, Home)
}

View File

@@ -2,14 +2,20 @@ run:
timeout: 5m
issues-exit-code: 1
tests: true
skip-dirs:
- local
issues:
max-same-issues: 100
include:
- EXC0012
- EXC0014
exclude-dirs:
- local
exclude-rules:
- path: example_test.go
linters:
- revive
text: "seems to be unused"
fix: true
linters:
enable:
@@ -29,21 +35,10 @@ linters:
- whitespace
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
formats:
- format: colored-line-number
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# make issues output unique by line, default is true
uniq-by-line: true
# add a prefix to the output file references; default is no prefix
path-prefix: ""
# sorts results by: filepath, line and column
sort-results: true
linters-settings:
golint:
min-confidence: 0.8
fix: true

View File

@@ -1,4 +1,4 @@
.PHONY: fmt lint test mocks test_coverage
.PHONY: fmt lint test mocks test_coverage test_ci
GO_PKGS := $(shell go list -f {{.Dir}} ./...)
@@ -15,5 +15,8 @@ test:
test_coverage:
@go test -race -v $(GO_FLAGS) -count=1 -coverprofile=coverage.out -covermode=atomic $(GO_PKGS)
test_ci:
@TEST_ENV=ci go test -race -v $(GO_FLAGS) -count=1 $(GO_PKGS)
mocks:
@go generate ./...

View File

@@ -53,6 +53,11 @@ func main() {
// start the scheduler
s.Start()
// block until you are ready to shut down
select {
case <-time.After(time.Minute):
}
// when you're done, shut it down
err = s.Shutdown()
if err != nil {
@@ -61,6 +66,11 @@ func main() {
}
```
## Examples
- [Go doc examples](https://pkg.go.dev/github.com/go-co-op/gocron/v2#pkg-examples)
- [Examples directory](examples)
## Concepts
- **Job**: The job encapsulates a "task", which is made up of a go function and any function parameters. The Job then
@@ -88,7 +98,7 @@ Jobs can be run every x weeks on specific days of the week and at specific times
- [**Monthly**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#MonthlyJob):
Jobs can be run every x months on specific days of the month and at specific times.
- [**One time**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#OneTimeJob):
Jobs can be run once at a specific time. These are non-recurring jobs.
Jobs can be run at specific time(s) (either once or many times).
### Concurrency Limits
Jobs can be limited individually or across the entire scheduler.
@@ -106,10 +116,13 @@ Multiple instances of gocron can be run.
- [**Elector**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedElector):
An elector can be used to elect a single instance of gocron to run as the primary with the
other instances checking to see if a new leader needs to be elected.
- Implementations: [go-co-op electors](https://github.com/go-co-op?q=-elector&type=all&language=&sort=)
- Implementations: [go-co-op electors](https://github.com/go-co-op?q=-elector&type=all&language=&sort=)
(don't see what you need? request on slack to get a repo created to contribute it!)
- [**Locker**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedLocker):
A locker can be used to lock each run of a job to a single instance of gocron.
- Implementations: [go-co-op lockers](https://github.com/go-co-op?q=-lock&type=all&language=&sort=)
Locker can be at job or scheduler, if it is defined both at job and scheduler then locker of job will take precedence.
- Implementations: [go-co-op lockers](https://github.com/go-co-op?q=-lock&type=all&language=&sort=)
(don't see what you need? request on slack to get a repo created to contribute it!)
### Events
Job events can trigger actions.
@@ -135,6 +148,13 @@ Logs can be enabled.
The Logger interface can be implemented with your desired logging library.
The provided NewLogger uses the standard library's log package.
### Metrics
Metrics may be collected from the execution of each job.
- [**Monitor**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Monitor):
A monitor can be used to collect metrics for each job from a scheduler.
- Implementations: [go-co-op monitors](https://github.com/go-co-op?q=-monitor&type=all&language=&sort=)
(don't see what you need? request on slack to get a repo created to contribute it!)
### Testing
The gocron library is set up to enable testing.
- Mocks are provided in [the mock package](mocks) using [gomock](https://github.com/uber-go/mock).

View File

@@ -2,14 +2,15 @@
## Supported Versions
The current plan is to maintain version 1 as long as possible incorporating any necessary security patches.
The current plan is to maintain version 2 as long as possible incorporating any necessary security patches. Version 1 is deprecated and will no longer be patched.
| Version | Supported |
| ------- | ------------------ |
| 1.x.x | :white_check_mark: |
| 1.x.x | :heavy_multiplication_x: |
| 2.x.x | :white_check_mark: |
## Reporting a Vulnerability
Vulnerabilities can be reported by [opening an issue](https://github.com/go-co-op/gocron/issues/new/choose) or reaching out on Slack: [<img src="https://img.shields.io/badge/gophers-gocron-brightgreen?logo=slack">](https://gophers.slack.com/archives/CQ7T0T1FW)
We will do our best to addrerss any vulnerabilities in an expeditious manner.
We will do our best to address any vulnerabilities in an expeditious manner.

View File

@@ -1,5 +0,0 @@
coverage:
status:
project:
default:
if_ci_failed: success

View File

@@ -9,6 +9,7 @@ var (
ErrDailyJobAtTimesNil = fmt.Errorf("gocron: DailyJob: atTimes must not be nil")
ErrDailyJobHours = fmt.Errorf("gocron: DailyJob: atTimes hours must be between 0 and 23 inclusive")
ErrDailyJobMinutesSeconds = fmt.Errorf("gocron: DailyJob: atTimes minutes and seconds must be between 0 and 59 inclusive")
ErrDurationJobIntervalZero = fmt.Errorf("gocron: DurationJob: time interval is 0")
ErrDurationRandomJobMinMax = fmt.Errorf("gocron: DurationRandomJob: minimum duration must be less than maximum duration")
ErrEventListenerFuncNil = fmt.Errorf("gocron: eventListenerFunc must not be nil")
ErrJobNotFound = fmt.Errorf("gocron: job not found")
@@ -32,14 +33,21 @@ var (
ErrWeeklyJobDaysOfTheWeekNil = fmt.Errorf("gocron: WeeklyJob: daysOfTheWeek must not be nil")
ErrWeeklyJobHours = fmt.Errorf("gocron: WeeklyJob: atTimes hours must be between 0 and 23 inclusive")
ErrWeeklyJobMinutesSeconds = fmt.Errorf("gocron: WeeklyJob: atTimes minutes and seconds must be between 0 and 59 inclusive")
ErrPanicRecovered = fmt.Errorf("gocron: panic recovered")
ErrWithClockNil = fmt.Errorf("gocron: WithClock: clock must not be nil")
ErrWithDistributedElectorNil = fmt.Errorf("gocron: WithDistributedElector: elector must not be nil")
ErrWithDistributedLockerNil = fmt.Errorf("gocron: WithDistributedLocker: locker must not be nil")
ErrWithDistributedJobLockerNil = fmt.Errorf("gocron: WithDistributedJobLocker: locker must not be nil")
ErrWithIdentifierNil = fmt.Errorf("gocron: WithIdentifier: identifier must not be nil")
ErrWithLimitConcurrentJobsZero = fmt.Errorf("gocron: WithLimitConcurrentJobs: limit must be greater than 0")
ErrWithLocationNil = fmt.Errorf("gocron: WithLocation: location must not be nil")
ErrWithLoggerNil = fmt.Errorf("gocron: WithLogger: logger must not be nil")
ErrWithMonitorNil = fmt.Errorf("gocron: WithMonitor: monitor must not be nil")
ErrWithNameEmpty = fmt.Errorf("gocron: WithName: name must not be empty")
ErrWithStartDateTimePast = fmt.Errorf("gocron: WithStartDateTime: start must not be in the past")
ErrWithStopDateTimePast = fmt.Errorf("gocron: WithStopDateTime: end must not be in the past")
ErrStartTimeLaterThanEndTime = fmt.Errorf("gocron: WithStartDateTime: start must not be later than end")
ErrStopTimeEarlierThanStartTime = fmt.Errorf("gocron: WithStopDateTime: end must not be earlier than start")
ErrWithStopTimeoutZeroOrNegative = fmt.Errorf("gocron: WithStopTimeout: timeout must be greater than 0")
)

View File

@@ -2,27 +2,53 @@ package gocron
import (
"context"
"fmt"
"strconv"
"sync"
"time"
"github.com/jonboulle/clockwork"
"github.com/google/uuid"
)
type executor struct {
ctx context.Context
cancel context.CancelFunc
logger Logger
stopCh chan struct{}
jobsIn chan jobIn
jobIDsOut chan uuid.UUID
jobOutRequest chan jobOutRequest
stopTimeout time.Duration
done chan error
singletonRunners map[uuid.UUID]singletonRunner
limitMode *limitModeConfig
elector Elector
locker Locker
// context used for shutting down
ctx context.Context
// cancel used by the executor to signal a stop of it's functions
cancel context.CancelFunc
// clock used for regular time or mocking time
clock clockwork.Clock
// the executor's logger
logger Logger
// receives jobs scheduled to execute
jobsIn chan jobIn
// sends out jobs for rescheduling
jobsOutForRescheduling chan uuid.UUID
// sends out jobs once completed
jobsOutCompleted chan uuid.UUID
// used to request jobs from the scheduler
jobOutRequest chan jobOutRequest
// used by the executor to receive a stop signal from the scheduler
stopCh chan struct{}
// the timeout value when stopping
stopTimeout time.Duration
// used to signal that the executor has completed shutdown
done chan error
// runners for any singleton type jobs
// map[uuid.UUID]singletonRunner
singletonRunners *sync.Map
// config for limit mode
limitMode *limitModeConfig
// the elector when running distributed instances
elector Elector
// the locker when running distributed instances
locker Locker
// monitor for reporting metrics
monitor Monitor
}
type jobIn struct {
@@ -66,7 +92,7 @@ func (e *executor) start() {
limitModeJobsWg := &waitGroupWithMutex{}
// create a fresh map for tracking singleton runners
e.singletonRunners = make(map[uuid.UUID]singletonRunner)
e.singletonRunners = &sync.Map{}
// start the for leap that is the executor
// selecting on channels for work to do
@@ -121,12 +147,7 @@ func (e *executor) start() {
// all runners are busy, reschedule the work for later
// which means we just skip it here and do nothing
// TODO when metrics are added, this should increment a rescheduled metric
if jIn.shouldSendOut {
select {
case e.jobIDsOut <- jIn.id:
default:
}
}
e.sendOutForRescheduling(&jIn)
}
} else {
// since we're not using LimitModeReschedule, but instead using LimitModeWait
@@ -134,6 +155,7 @@ func (e *executor) start() {
// to work through the channel backlog. A hard limit of 1000 is in place
// at which point this call would block.
// TODO when metrics are added, this should increment a wait metric
e.sendOutForRescheduling(&jIn)
e.limitMode.in <- jIn
}
} else {
@@ -150,15 +172,18 @@ func (e *executor) start() {
if j.singletonMode {
// for singleton mode, get the existing runner for the job
// or spin up a new one
runner, ok := e.singletonRunners[jIn.id]
runner := &singletonRunner{}
runnerSrc, ok := e.singletonRunners.Load(jIn.id)
if !ok {
runner.in = make(chan jobIn, 1000)
if j.singletonLimitMode == LimitModeReschedule {
runner.rescheduleLimiter = make(chan struct{}, 1)
}
e.singletonRunners[jIn.id] = runner
e.singletonRunners.Store(jIn.id, runner)
singletonJobsWg.Add(1)
go e.singletonModeRunner("singleton-"+jIn.id.String(), runner.in, singletonJobsWg, j.singletonLimitMode, runner.rescheduleLimiter)
} else {
runner = runnerSrc.(*singletonRunner)
}
if j.singletonLimitMode == LimitModeReschedule {
@@ -167,20 +192,17 @@ func (e *executor) start() {
select {
case runner.rescheduleLimiter <- struct{}{}:
runner.in <- jIn
e.sendOutForRescheduling(&jIn)
default:
// runner is busy, reschedule the work for later
// which means we just skip it here and do nothing
// TODO when metrics are added, this should increment a rescheduled metric
if jIn.shouldSendOut {
select {
case e.jobIDsOut <- jIn.id:
default:
}
}
e.sendOutForRescheduling(&jIn)
}
} else {
// wait mode, fill up that queue (buffered channel, so it's ok)
runner.in <- jIn
e.sendOutForRescheduling(&jIn)
}
} else {
select {
@@ -196,7 +218,7 @@ func (e *executor) start() {
// complete.
standardJobsWg.Add(1)
go func(j internalJob) {
e.runJob(j, jIn.shouldSendOut)
e.runJob(j, jIn)
standardJobsWg.Done()
}(*j)
}
@@ -209,6 +231,20 @@ func (e *executor) start() {
}
}
func (e *executor) sendOutForRescheduling(jIn *jobIn) {
if jIn.shouldSendOut {
select {
case e.jobsOutForRescheduling <- jIn.id:
case <-e.ctx.Done():
return
}
}
// we need to set this to false now, because to handle
// non-limit jobs, we send out from the e.runJob function
// and in this case we don't want to send out twice.
jIn.shouldSendOut = false
}
func (e *executor) limitModeRunner(name string, in chan jobIn, wg *waitGroupWithMutex, limitMode LimitMode, rescheduleLimiter chan struct{}) {
e.logger.Debug("gocron: limitModeRunner starting", "name", name)
for {
@@ -239,24 +275,21 @@ func (e *executor) limitModeRunner(name string, in chan jobIn, wg *waitGroupWith
return
case <-j.ctx.Done():
return
case e.jobIDsOut <- j.id:
case e.jobsOutForRescheduling <- j.id:
}
}
// remove the limiter block, as this particular job
// was a singleton already running, and we want to
// allow another job to be scheduled
if limitMode == LimitModeReschedule {
select {
case <-rescheduleLimiter:
default:
}
<-rescheduleLimiter
}
continue
}
e.limitMode.singletonJobs[jIn.id] = struct{}{}
e.limitMode.singletonJobsMu.Unlock()
}
e.runJob(*j, jIn.shouldSendOut)
e.runJob(*j, jIn)
if j.singletonMode {
e.limitMode.singletonJobsMu.Lock()
@@ -267,10 +300,7 @@ func (e *executor) limitModeRunner(name string, in chan jobIn, wg *waitGroupWith
// remove the limiter block to allow another job to be scheduled
if limitMode == LimitModeReschedule {
select {
case <-rescheduleLimiter:
default:
}
<-rescheduleLimiter
}
case <-e.ctx.Done():
e.logger.Debug("limitModeRunner shutting down", "name", name)
@@ -297,15 +327,16 @@ func (e *executor) singletonModeRunner(name string, in chan jobIn, wg *waitGroup
j := requestJobCtx(ctx, jIn.id, e.jobOutRequest)
cancel()
if j != nil {
e.runJob(*j, jIn.shouldSendOut)
// need to set shouldSendOut = false here, as there is a duplicative call to sendOutForRescheduling
// inside the runJob function that needs to be skipped. sendOutForRescheduling is previously called
// when the job is sent to the singleton mode runner.
jIn.shouldSendOut = false
e.runJob(*j, jIn)
}
// remove the limiter block to allow another job to be scheduled
if limitMode == LimitModeReschedule {
select {
case <-rescheduleLimiter:
default:
}
<-rescheduleLimiter
}
case <-e.ctx.Done():
e.logger.Debug("singletonModeRunner shutting down", "name", name)
@@ -315,7 +346,7 @@ func (e *executor) singletonModeRunner(name string, in chan jobIn, wg *waitGroup
}
}
func (e *executor) runJob(j internalJob, shouldSendOut bool) {
func (e *executor) runJob(j internalJob, jIn jobIn) {
if j.ctx == nil {
return
}
@@ -327,34 +358,73 @@ func (e *executor) runJob(j internalJob, shouldSendOut bool) {
default:
}
if j.stopTimeReached(e.clock.Now()) {
return
}
if e.elector != nil {
if err := e.elector.IsLeader(j.ctx); err != nil {
e.sendOutForRescheduling(&jIn)
e.incrementJobCounter(j, Skip)
return
}
} else if j.locker != nil {
lock, err := j.locker.Lock(j.ctx, j.name)
if err != nil {
_ = callJobFuncWithParams(j.afterLockError, j.id, j.name, err)
e.sendOutForRescheduling(&jIn)
e.incrementJobCounter(j, Skip)
return
}
defer func() { _ = lock.Unlock(j.ctx) }()
} else if e.locker != nil {
lock, err := e.locker.Lock(j.ctx, j.name)
if err != nil {
_ = callJobFuncWithParams(j.afterLockError, j.id, j.name, err)
e.sendOutForRescheduling(&jIn)
e.incrementJobCounter(j, Skip)
return
}
defer func() { _ = lock.Unlock(j.ctx) }()
}
_ = callJobFuncWithParams(j.beforeJobRuns, j.id, j.name)
if shouldSendOut {
select {
case <-e.ctx.Done():
return
case <-j.ctx.Done():
return
case e.jobIDsOut <- j.id:
}
e.sendOutForRescheduling(&jIn)
select {
case e.jobsOutCompleted <- j.id:
case <-e.ctx.Done():
}
err := callJobFuncWithParams(j.function, j.parameters...)
startTime := time.Now()
err := e.callJobWithRecover(j)
if e.monitor != nil {
e.monitor.RecordJobTiming(startTime, time.Now(), j.id, j.name, j.tags)
}
if err != nil {
_ = callJobFuncWithParams(j.afterJobRunsWithError, j.id, j.name, err)
e.incrementJobCounter(j, Fail)
} else {
_ = callJobFuncWithParams(j.afterJobRuns, j.id, j.name)
e.incrementJobCounter(j, Success)
}
}
func (e *executor) callJobWithRecover(j internalJob) (err error) {
defer func() {
if recoverData := recover(); recoverData != nil {
_ = callJobFuncWithParams(j.afterJobRunsWithPanic, j.id, j.name, recoverData)
// if panic is occurred, we should return an error
err = fmt.Errorf("%w from %v", ErrPanicRecovered, recoverData)
}
}()
return callJobFuncWithParams(j.function, j.parameters...)
}
func (e *executor) incrementJobCounter(j internalJob, status JobStatus) {
if e.monitor != nil {
e.monitor.IncrementJob(j.id, j.name, j.tags, status)
}
}
@@ -437,4 +507,8 @@ func (e *executor) stop(standardJobsWg, singletonJobsWg, limitModeJobsWg *waitGr
e.logger.Debug("gocron: executor stopped")
}
waiterCancel()
if e.limitMode != nil {
e.limitMode.started = false
}
}

View File

@@ -24,7 +24,12 @@ type internalJob struct {
name string
tags []string
jobSchedule
lastRun, nextRun time.Time
// as some jobs may queue up, it's possible to
// have multiple nextScheduled times
nextScheduled []time.Time
lastRun time.Time
function any
parameters []any
timer clockwork.Timer
@@ -33,10 +38,15 @@ type internalJob struct {
limitRunsTo *limitRunsTo
startTime time.Time
startImmediately bool
stopTime time.Time
// event listeners
afterJobRuns func(jobID uuid.UUID, jobName string)
beforeJobRuns func(jobID uuid.UUID, jobName string)
afterJobRunsWithError func(jobID uuid.UUID, jobName string, err error)
afterJobRunsWithPanic func(jobID uuid.UUID, jobName string, recoverData any)
afterLockError func(jobID uuid.UUID, jobName string, err error)
locker Locker
}
// stop is used to stop the job's timer and cancel the context
@@ -51,6 +61,13 @@ func (j *internalJob) stop() {
j.cancel()
}
func (j *internalJob) stopTimeReached(now time.Time) bool {
if j.stopTime.IsZero() {
return false
}
return j.stopTime.Before(now)
}
// task stores the function and parameters
// that are actually run when the job is executed.
type task struct {
@@ -89,7 +106,7 @@ type limitRunsTo struct {
// JobDefinition defines the interface that must be
// implemented to create a job from the definition.
type JobDefinition interface {
setup(*internalJob, *time.Location) error
setup(j *internalJob, l *time.Location, now time.Time) error
}
var _ JobDefinition = (*cronJobDefinition)(nil)
@@ -99,7 +116,7 @@ type cronJobDefinition struct {
withSeconds bool
}
func (c cronJobDefinition) setup(j *internalJob, location *time.Location) error {
func (c cronJobDefinition) setup(j *internalJob, location *time.Location, _ time.Time) error {
var withLocation string
if strings.HasPrefix(c.crontab, "TZ=") || strings.HasPrefix(c.crontab, "CRON_TZ=") {
withLocation = c.crontab
@@ -115,7 +132,7 @@ func (c cronJobDefinition) setup(j *internalJob, location *time.Location) error
)
if c.withSeconds {
p := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
p := cron.NewParser(cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
cronSchedule, err = p.Parse(withLocation)
} else {
cronSchedule, err = cron.ParseStandard(withLocation)
@@ -147,7 +164,10 @@ type durationJobDefinition struct {
duration time.Duration
}
func (d durationJobDefinition) setup(j *internalJob, _ *time.Location) error {
func (d durationJobDefinition) setup(j *internalJob, _ *time.Location, _ time.Time) error {
if d.duration == 0 {
return ErrDurationJobIntervalZero
}
j.jobSchedule = &durationJob{duration: d.duration}
return nil
}
@@ -166,7 +186,7 @@ type durationRandomJobDefinition struct {
min, max time.Duration
}
func (d durationRandomJobDefinition) setup(j *internalJob, _ *time.Location) error {
func (d durationRandomJobDefinition) setup(j *internalJob, _ *time.Location, _ time.Time) error {
if d.min >= d.max {
return ErrDurationRandomJobMinMax
}
@@ -216,7 +236,7 @@ type dailyJobDefinition struct {
atTimes AtTimes
}
func (d dailyJobDefinition) setup(j *internalJob, location *time.Location) error {
func (d dailyJobDefinition) setup(j *internalJob, location *time.Location, _ time.Time) error {
atTimesDate, err := convertAtTimesToDateTime(d.atTimes, location)
switch {
case errors.Is(err, errAtTimesNil):
@@ -245,7 +265,7 @@ type weeklyJobDefinition struct {
atTimes AtTimes
}
func (w weeklyJobDefinition) setup(j *internalJob, location *time.Location) error {
func (w weeklyJobDefinition) setup(j *internalJob, location *time.Location, _ time.Time) error {
var ws weeklyJob
ws.interval = w.interval
@@ -281,7 +301,8 @@ type Weekdays func() []time.Weekday
// NewWeekdays provide the days of the week the job should run.
func NewWeekdays(weekday time.Weekday, weekdays ...time.Weekday) Weekdays {
return func() []time.Weekday {
return append(weekdays, weekday)
weekdays = append(weekdays, weekday)
return weekdays
}
}
@@ -309,7 +330,7 @@ type monthlyJobDefinition struct {
atTimes AtTimes
}
func (m monthlyJobDefinition) setup(j *internalJob, location *time.Location) error {
func (m monthlyJobDefinition) setup(j *internalJob, location *time.Location, _ time.Time) error {
var ms monthlyJob
ms.interval = m.interval
@@ -432,31 +453,46 @@ type oneTimeJobDefinition struct {
startAt OneTimeJobStartAtOption
}
func (o oneTimeJobDefinition) setup(j *internalJob, _ *time.Location) error {
j.jobSchedule = oneTimeJob{}
return o.startAt(j)
func (o oneTimeJobDefinition) setup(j *internalJob, _ *time.Location, now time.Time) error {
sortedTimes := o.startAt(j)
slices.SortStableFunc(sortedTimes, ascendingTime)
// keep only schedules that are in the future
idx, found := slices.BinarySearchFunc(sortedTimes, now, ascendingTime)
if found {
idx++
}
sortedTimes = sortedTimes[idx:]
if !j.startImmediately && len(sortedTimes) == 0 {
return ErrOneTimeJobStartDateTimePast
}
j.jobSchedule = oneTimeJob{sortedTimes: sortedTimes}
return nil
}
// OneTimeJobStartAtOption defines when the one time job is run
type OneTimeJobStartAtOption func(*internalJob) error
type OneTimeJobStartAtOption func(*internalJob) []time.Time
// OneTimeJobStartImmediately tells the scheduler to run the one time job immediately.
func OneTimeJobStartImmediately() OneTimeJobStartAtOption {
return func(j *internalJob) error {
return func(j *internalJob) []time.Time {
j.startImmediately = true
return nil
return []time.Time{}
}
}
// OneTimeJobStartDateTime sets the date & time at which the job should run.
// This datetime must be in the future.
// This datetime must be in the future (according to the scheduler clock).
func OneTimeJobStartDateTime(start time.Time) OneTimeJobStartAtOption {
return func(j *internalJob) error {
if start.IsZero() || start.Before(time.Now()) {
return ErrOneTimeJobStartDateTimePast
}
j.startTime = start
return nil
return func(_ *internalJob) []time.Time {
return []time.Time{start}
}
}
// OneTimeJobStartDateTimes sets the date & times at which the job should run.
// At least one of the date/times must be in the future (according to the scheduler clock).
func OneTimeJobStartDateTimes(times ...time.Time) OneTimeJobStartAtOption {
return func(_ *internalJob) []time.Time {
return times
}
}
@@ -475,12 +511,25 @@ func OneTimeJob(startAt OneTimeJobStartAtOption) JobDefinition {
// -----------------------------------------------
// JobOption defines the constructor for job options.
type JobOption func(*internalJob) error
type JobOption func(*internalJob, time.Time) error
// WithDistributedJobLocker sets the locker to be used by multiple
// Scheduler instances to ensure that only one instance of each
// job is run.
func WithDistributedJobLocker(locker Locker) JobOption {
return func(j *internalJob, _ time.Time) error {
if locker == nil {
return ErrWithDistributedJobLockerNil
}
j.locker = locker
return nil
}
}
// WithEventListeners sets the event listeners that should be
// run for the job.
func WithEventListeners(eventListeners ...EventListener) JobOption {
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
for _, eventListener := range eventListeners {
if err := eventListener(j); err != nil {
return err
@@ -493,7 +542,7 @@ func WithEventListeners(eventListeners ...EventListener) JobOption {
// WithLimitedRuns limits the number of executions of this job to n.
// Upon reaching the limit, the job is removed from the scheduler.
func WithLimitedRuns(limit uint) JobOption {
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
j.limitRunsTo = &limitRunsTo{
limit: limit,
runCount: 0,
@@ -505,8 +554,7 @@ func WithLimitedRuns(limit uint) JobOption {
// WithName sets the name of the job. Name provides
// a human-readable identifier for the job.
func WithName(name string) JobOption {
// TODO use the name for metrics and future logging option
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
if name == "" {
return ErrWithNameEmpty
}
@@ -519,7 +567,7 @@ func WithName(name string) JobOption {
// This is useful for jobs that should not overlap, and that occasionally
// (but not consistently) run longer than the interval between job runs.
func WithSingletonMode(mode LimitMode) JobOption {
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
j.singletonMode = true
j.singletonLimitMode = mode
return nil
@@ -529,19 +577,19 @@ func WithSingletonMode(mode LimitMode) JobOption {
// WithStartAt sets the option for starting the job at
// a specific datetime.
func WithStartAt(option StartAtOption) JobOption {
return func(j *internalJob) error {
return option(j)
return func(j *internalJob, now time.Time) error {
return option(j, now)
}
}
// StartAtOption defines options for starting the job
type StartAtOption func(*internalJob) error
type StartAtOption func(*internalJob, time.Time) error
// WithStartImmediately tells the scheduler to run the job immediately
// regardless of the type or schedule of job. After this immediate run
// the job is scheduled from this time based on the job definition.
func WithStartImmediately() StartAtOption {
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
j.startImmediately = true
return nil
}
@@ -550,25 +598,69 @@ func WithStartImmediately() StartAtOption {
// WithStartDateTime sets the first date & time at which the job should run.
// This datetime must be in the future.
func WithStartDateTime(start time.Time) StartAtOption {
return func(j *internalJob) error {
if start.IsZero() || start.Before(time.Now()) {
return func(j *internalJob, now time.Time) error {
if start.IsZero() || start.Before(now) {
return ErrWithStartDateTimePast
}
if !j.stopTime.IsZero() && j.stopTime.Before(start) {
return ErrStartTimeLaterThanEndTime
}
j.startTime = start
return nil
}
}
// WithStopAt sets the option for stopping the job from running
// after the specified time.
func WithStopAt(option StopAtOption) JobOption {
return func(j *internalJob, now time.Time) error {
return option(j, now)
}
}
// StopAtOption defines options for stopping the job
type StopAtOption func(*internalJob, time.Time) error
// WithStopDateTime sets the final date & time after which the job should stop.
// This must be in the future and should be after the startTime (if specified).
// The job's final run may be at the stop time, but not after.
func WithStopDateTime(end time.Time) StopAtOption {
return func(j *internalJob, now time.Time) error {
if end.IsZero() || end.Before(now) {
return ErrWithStopDateTimePast
}
if end.Before(j.startTime) {
return ErrStopTimeEarlierThanStartTime
}
j.stopTime = end
return nil
}
}
// WithTags sets the tags for the job. Tags provide
// a way to identify jobs by a set of tags and remove
// multiple jobs by tag.
func WithTags(tags ...string) JobOption {
return func(j *internalJob) error {
return func(j *internalJob, _ time.Time) error {
j.tags = tags
return nil
}
}
// WithIdentifier sets the identifier for the job. The identifier
// is used to uniquely identify the job and is used for logging
// and metrics.
func WithIdentifier(id uuid.UUID) JobOption {
return func(j *internalJob, _ time.Time) error {
if id == uuid.Nil {
return ErrWithIdentifierNil
}
j.id = id
return nil
}
}
// -----------------------------------------------
// -----------------------------------------------
// ------------- Job Event Listeners -------------
@@ -579,8 +671,20 @@ func WithTags(tags ...string) JobOption {
// listeners that can be used to listen for job events.
type EventListener func(*internalJob) error
// AfterJobRuns is used to listen for when a job has run regardless
// of any returned error value, and run the provided function.
// BeforeJobRuns is used to listen for when a job is about to run and
// then run the provided function.
func BeforeJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
return func(j *internalJob) error {
if eventListenerFunc == nil {
return ErrEventListenerFuncNil
}
j.beforeJobRuns = eventListenerFunc
return nil
}
}
// AfterJobRuns is used to listen for when a job has run
// without an error, and then run the provided function.
func AfterJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
return func(j *internalJob) error {
if eventListenerFunc == nil {
@@ -603,14 +707,26 @@ func AfterJobRunsWithError(eventListenerFunc func(jobID uuid.UUID, jobName strin
}
}
// BeforeJobRuns is used to listen for when a job is about to run and
// then run the provided function.
func BeforeJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
// AfterJobRunsWithPanic is used to listen for when a job has run and
// returned panicked recover data, and then run the provided function.
func AfterJobRunsWithPanic(eventListenerFunc func(jobID uuid.UUID, jobName string, recoverData any)) EventListener {
return func(j *internalJob) error {
if eventListenerFunc == nil {
return ErrEventListenerFuncNil
}
j.beforeJobRuns = eventListenerFunc
j.afterJobRunsWithPanic = eventListenerFunc
return nil
}
}
// AfterLockError is used to when the distributed locker returns an error and
// then run the provided function.
func AfterLockError(eventListenerFunc func(jobID uuid.UUID, jobName string, err error)) EventListener {
return func(j *internalJob) error {
if eventListenerFunc == nil {
return ErrEventListenerFuncNil
}
j.afterLockError = eventListenerFunc
return nil
}
}
@@ -678,18 +794,18 @@ func (d dailyJob) next(lastRun time.Time) time.Time {
func (d dailyJob) nextDay(lastRun time.Time, firstPass bool) time.Time {
for _, at := range d.atTimes {
// sub the at time hour/min/sec onto the lastRun's values
// sub the at time hour/min/sec onto the lastScheduledRun's values
// to use in checks to see if we've got our next run time
atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day(), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location())
if firstPass && atDate.After(lastRun) {
// checking to see if it is after i.e. greater than,
// and not greater or equal as our lastRun day/time
// and not greater or equal as our lastScheduledRun day/time
// will be in the loop, and we don't want to select it again
return atDate
} else if !firstPass && !atDate.Before(lastRun) {
// now that we're looking at the next day, it's ok to consider
// the same at time that was last run (as lastRun has been incremented)
// the same at time that was last run (as lastScheduledRun has been incremented)
return atDate
}
}
@@ -724,18 +840,18 @@ func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time, firstPass bool) time.Tim
// weekDayDiff is used to add the correct amount to the atDate day below
weekDayDiff := wd - lastRun.Weekday()
for _, at := range w.atTimes {
// sub the at time hour/min/sec onto the lastRun's values
// sub the at time hour/min/sec onto the lastScheduledRun's values
// to use in checks to see if we've got our next run time
atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(weekDayDiff), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location())
if firstPass && atDate.After(lastRun) {
// checking to see if it is after i.e. greater than,
// and not greater or equal as our lastRun day/time
// and not greater or equal as our lastScheduledRun day/time
// will be in the loop, and we don't want to select it again
return atDate
} else if !firstPass && !atDate.Before(lastRun) {
// now that we're looking at the next week, it's ok to consider
// the same at time that was last run (as lastRun has been incremented)
// the same at time that was last run (as lastScheduledRun has been incremented)
return atDate
}
}
@@ -756,38 +872,43 @@ type monthlyJob struct {
func (m monthlyJob) next(lastRun time.Time) time.Time {
daysList := make([]int, len(m.days))
copy(daysList, m.days)
firstDayNextMonth := time.Date(lastRun.Year(), lastRun.Month()+1, 1, 0, 0, 0, 0, lastRun.Location())
for _, daySub := range m.daysFromEnd {
// getting a combined list of all the daysList and the negative daysList
// which count backwards from the first day of the next month
// -1 == the last day of the month
day := firstDayNextMonth.AddDate(0, 0, daySub).Day()
daysList = append(daysList, day)
}
slices.Sort(daysList)
firstPass := true
next := m.nextMonthDayAtTime(lastRun, daysList, firstPass)
daysFromEnd := m.handleNegativeDays(lastRun, daysList, m.daysFromEnd)
next := m.nextMonthDayAtTime(lastRun, daysFromEnd, true)
if !next.IsZero() {
return next
}
firstPass = false
from := time.Date(lastRun.Year(), lastRun.Month()+time.Month(m.interval), 1, 0, 0, 0, 0, lastRun.Location())
for next.IsZero() {
next = m.nextMonthDayAtTime(from, daysList, firstPass)
daysFromEnd = m.handleNegativeDays(from, daysList, m.daysFromEnd)
next = m.nextMonthDayAtTime(from, daysFromEnd, false)
from = from.AddDate(0, int(m.interval), 0)
}
return next
}
func (m monthlyJob) handleNegativeDays(from time.Time, days, negativeDays []int) []int {
var out []int
// getting a list of the days from the end of the following month
// -1 == the last day of the month
firstDayNextMonth := time.Date(from.Year(), from.Month()+1, 1, 0, 0, 0, 0, from.Location())
for _, daySub := range negativeDays {
day := firstDayNextMonth.AddDate(0, 0, daySub).Day()
out = append(out, day)
}
out = append(out, days...)
slices.Sort(out)
return out
}
func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int, firstPass bool) time.Time {
// find the next day in the month that should run and then check for an at time
for _, day := range days {
if day >= lastRun.Day() {
for _, at := range m.atTimes {
// sub the day, and the at time hour/min/sec onto the lastRun's values
// sub the day, and the at time hour/min/sec onto the lastScheduledRun's values
// to use in checks to see if we've got our next run time
atDate := time.Date(lastRun.Year(), lastRun.Month(), day, at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location())
@@ -799,12 +920,12 @@ func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int, firstPass
if firstPass && atDate.After(lastRun) {
// checking to see if it is after i.e. greater than,
// and not greater or equal as our lastRun day/time
// and not greater or equal as our lastScheduledRun day/time
// will be in the loop, and we don't want to select it again
return atDate
} else if !firstPass && !atDate.Before(lastRun) {
// now that we're looking at the next month, it's ok to consider
// the same at time that was lastRun (as lastRun has been incremented)
// the same at time that was lastScheduledRun (as lastScheduledRun has been incremented)
return atDate
}
}
@@ -816,10 +937,33 @@ func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int, firstPass
var _ jobSchedule = (*oneTimeJob)(nil)
type oneTimeJob struct{}
type oneTimeJob struct {
sortedTimes []time.Time
}
func (o oneTimeJob) next(_ time.Time) time.Time {
return time.Time{}
// next finds the next item in a sorted list of times using binary-search.
//
// example: sortedTimes: [2, 4, 6, 8]
//
// lastRun: 1 => [idx=0,found=false] => next is 2 - sorted[idx] idx=0
// lastRun: 2 => [idx=0,found=true] => next is 4 - sorted[idx+1] idx=1
// lastRun: 3 => [idx=1,found=false] => next is 4 - sorted[idx] idx=1
// lastRun: 4 => [idx=1,found=true] => next is 6 - sorted[idx+1] idx=2
// lastRun: 7 => [idx=3,found=false] => next is 8 - sorted[idx] idx=3
// lastRun: 8 => [idx=3,found=found] => next is none
// lastRun: 9 => [idx=3,found=found] => next is none
func (o oneTimeJob) next(lastRun time.Time) time.Time {
idx, found := slices.BinarySearchFunc(o.sortedTimes, lastRun, ascendingTime)
// if found, the next run is the following index
if found {
idx++
}
// exhausted runs
if idx >= len(o.sortedTimes) {
return time.Time{}
}
return o.sortedTimes[idx]
}
// -----------------------------------------------
@@ -839,9 +983,13 @@ type Job interface {
Name() string
// NextRun returns the time of the job's next scheduled run.
NextRun() (time.Time, error)
// NextRuns returns the requested number of calculated next run values.
NextRuns(int) ([]time.Time, error)
// RunNow runs the job once, now. This does not alter
// the existing run schedule, and will respect all job
// and scheduler limits.
// and scheduler limits. This means that running a job now may
// cause the job's regular interval to be rescheduled due to
// the instance being run by RunNow blocking your run limit.
RunNow() error
// Tags returns the job's string tags.
Tags() []string
@@ -882,7 +1030,39 @@ func (j job) NextRun() (time.Time, error) {
if ij == nil || ij.id == uuid.Nil {
return time.Time{}, ErrJobNotFound
}
return ij.nextRun, nil
if len(ij.nextScheduled) == 0 {
return time.Time{}, nil
}
// the first element is the next scheduled run with subsequent
// runs following after in the slice
return ij.nextScheduled[0], nil
}
func (j job) NextRuns(count int) ([]time.Time, error) {
ij := requestJob(j.id, j.jobOutRequest)
if ij == nil || ij.id == uuid.Nil {
return nil, ErrJobNotFound
}
lengthNextScheduled := len(ij.nextScheduled)
if lengthNextScheduled == 0 {
return nil, nil
} else if count <= lengthNextScheduled {
return ij.nextScheduled[:count], nil
}
out := make([]time.Time, count)
for i := 0; i < count; i++ {
if i < lengthNextScheduled {
out[i] = ij.nextScheduled[i]
continue
}
from := out[i-1]
out[i] = ij.next(from)
}
return out, nil
}
func (j job) Tags() []string {

27
vendor/github.com/go-co-op/gocron/v2/monitor.go generated vendored Normal file
View File

@@ -0,0 +1,27 @@
package gocron
import (
"time"
"github.com/google/uuid"
)
// JobStatus is the status of job run that should be collected with the metric.
type JobStatus string
// The different statuses of job that can be used.
const (
Fail JobStatus = "fail"
Success JobStatus = "success"
Skip JobStatus = "skip"
)
// Monitor represents the interface to collect jobs metrics.
type Monitor interface {
// IncrementJob will provide details about the job and expects the underlying implementation
// to handle instantiating and incrementing a value
IncrementJob(id uuid.UUID, name string, tags []string, status JobStatus)
// RecordJobTiming will provide details about the job and the timing and expects the underlying implementation
// to handle instantiating and recording the value
RecordJobTiming(startTime, endTime time.Time, id uuid.UUID, name string, tags []string)
}

View File

@@ -44,6 +44,9 @@ type Scheduler interface {
// Update replaces the existing Job's JobDefinition with the provided
// JobDefinition. The Job's Job.ID() remains the same.
Update(uuid.UUID, JobDefinition, Task, ...JobOption) (Job, error)
// JobsWaitingInQueue number of jobs waiting in Queue in case of LimitModeWait
// In case of LimitModeReschedule or no limit it will be always zero
JobsWaitingInQueue() int
}
// -----------------------------------------------
@@ -53,28 +56,52 @@ type Scheduler interface {
// -----------------------------------------------
type scheduler struct {
shutdownCtx context.Context
shutdownCancel context.CancelFunc
exec executor
jobs map[uuid.UUID]internalJob
location *time.Location
clock clockwork.Clock
started bool
// context used for shutting down
shutdownCtx context.Context
// cancel used to signal scheduler should shut down
shutdownCancel context.CancelFunc
// the executor, which actually runs the jobs sent to it via the scheduler
exec executor
// the map of jobs registered in the scheduler
jobs map[uuid.UUID]internalJob
// the location used by the scheduler for scheduling when relevant
location *time.Location
// whether the scheduler has been started or not
started bool
// globally applied JobOption's set on all jobs added to the scheduler
// note: individually set JobOption's take precedence.
globalJobOptions []JobOption
logger Logger
// the scheduler's logger
logger Logger
startCh chan struct{}
startedCh chan struct{}
stopCh chan struct{}
stopErrCh chan error
allJobsOutRequest chan allJobsOutRequest
jobOutRequestCh chan jobOutRequest
runJobRequestCh chan runJobRequest
newJobCh chan internalJob
removeJobCh chan uuid.UUID
// used to tell the scheduler to start
startCh chan struct{}
// used to report that the scheduler has started
startedCh chan struct{}
// used to tell the scheduler to stop
stopCh chan struct{}
// used to report that the scheduler has stopped
stopErrCh chan error
// used to send all the jobs out when a request is made by the client
allJobsOutRequest chan allJobsOutRequest
// used to send a jobs out when a request is made by the client
jobOutRequestCh chan jobOutRequest
// used to run a job on-demand when requested by the client
runJobRequestCh chan runJobRequest
// new jobs are received here
newJobCh chan newJobIn
// requests from the client to remove jobs by ID are received here
removeJobCh chan uuid.UUID
// requests from the client to remove jobs by tags are received here
removeJobsByTagsCh chan []string
}
type newJobIn struct {
ctx context.Context
cancel context.CancelFunc
job internalJob
}
type jobOutRequest struct {
id uuid.UUID
outChan chan internalJob
@@ -100,13 +127,15 @@ func NewScheduler(options ...SchedulerOption) (Scheduler, error) {
exec := executor{
stopCh: make(chan struct{}),
stopTimeout: time.Second * 10,
singletonRunners: make(map[uuid.UUID]singletonRunner),
singletonRunners: nil,
logger: &noOpLogger{},
clock: clockwork.NewRealClock(),
jobsIn: make(chan jobIn),
jobIDsOut: make(chan uuid.UUID),
jobOutRequest: make(chan jobOutRequest, 1000),
done: make(chan error),
jobsIn: make(chan jobIn),
jobsOutForRescheduling: make(chan uuid.UUID),
jobsOutCompleted: make(chan uuid.UUID),
jobOutRequest: make(chan jobOutRequest, 1000),
done: make(chan error),
}
s := &scheduler{
@@ -115,10 +144,9 @@ func NewScheduler(options ...SchedulerOption) (Scheduler, error) {
exec: exec,
jobs: make(map[uuid.UUID]internalJob),
location: time.Local,
clock: clockwork.NewRealClock(),
logger: &noOpLogger{},
newJobCh: make(chan internalJob),
newJobCh: make(chan newJobIn),
removeJobCh: make(chan uuid.UUID),
removeJobsByTagsCh: make(chan []string),
startCh: make(chan struct{}),
@@ -141,11 +169,14 @@ func NewScheduler(options ...SchedulerOption) (Scheduler, error) {
s.logger.Info("gocron: new scheduler created")
for {
select {
case id := <-s.exec.jobIDsOut:
s.selectExecJobIDsOut(id)
case id := <-s.exec.jobsOutForRescheduling:
s.selectExecJobsOutForRescheduling(id)
case j := <-s.newJobCh:
s.selectNewJob(j)
case id := <-s.exec.jobsOutCompleted:
s.selectExecJobsOutCompleted(id)
case in := <-s.newJobCh:
s.selectNewJob(in)
case id := <-s.removeJobCh:
s.selectRemoveJob(id)
@@ -281,9 +312,87 @@ func (s *scheduler) selectRemoveJob(id uuid.UUID) {
// Jobs coming back from the executor to the scheduler that
// need to evaluated for rescheduling.
func (s *scheduler) selectExecJobIDsOut(id uuid.UUID) {
j := s.jobs[id]
j.lastRun = j.nextRun
func (s *scheduler) selectExecJobsOutForRescheduling(id uuid.UUID) {
select {
case <-s.shutdownCtx.Done():
return
default:
}
j, ok := s.jobs[id]
if !ok {
// the job was removed while it was running, and
// so we don't need to reschedule it.
return
}
if j.stopTimeReached(s.now()) {
return
}
scheduleFrom := j.lastRun
if len(j.nextScheduled) > 0 {
// always grab the last element in the slice as that is the furthest
// out in the future and the time from which we want to calculate
// the subsequent next run time.
slices.SortStableFunc(j.nextScheduled, ascendingTime)
scheduleFrom = j.nextScheduled[len(j.nextScheduled)-1]
}
if scheduleFrom.IsZero() {
scheduleFrom = j.startTime
}
next := j.next(scheduleFrom)
if next.IsZero() {
// the job's next function will return zero for OneTime jobs.
// since they are one time only, they do not need rescheduling.
return
}
if next.Before(s.now()) {
// in some cases the next run time can be in the past, for example:
// - the time on the machine was incorrect and has been synced with ntp
// - the machine went to sleep, and woke up some time later
// in those cases, we want to increment to the next run in the future
// and schedule the job for that time.
for next.Before(s.now()) {
next = j.next(next)
}
}
j.nextScheduled = append(j.nextScheduled, next)
j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() {
// set the actual timer on the job here and listen for
// shut down events so that the job doesn't attempt to
// run if the scheduler has been shutdown.
select {
case <-s.shutdownCtx.Done():
return
case s.exec.jobsIn <- jobIn{
id: j.id,
shouldSendOut: true,
}:
}
})
// update the job with its new next and last run times and timer.
s.jobs[id] = j
}
func (s *scheduler) selectExecJobsOutCompleted(id uuid.UUID) {
j, ok := s.jobs[id]
if !ok {
return
}
// if the job has nextScheduled time in the past,
// we need to remove any that are in the past.
var newNextScheduled []time.Time
for _, t := range j.nextScheduled {
if t.Before(s.now()) {
continue
}
newNextScheduled = append(newNextScheduled, t)
}
j.nextScheduled = newNextScheduled
// if the job has a limited number of runs set, we need to
// check how many runs have occurred and stop running this
@@ -302,37 +411,7 @@ func (s *scheduler) selectExecJobIDsOut(id uuid.UUID) {
}
}
next := j.next(j.lastRun)
if next.IsZero() {
// the job's next function will return zero for OneTime jobs.
// since they are one time only, they do not need rescheduling.
return
}
if next.Before(s.now()) {
// in some cases the next run time can be in the past, for example:
// - the time on the machine was incorrect and has been synced with ntp
// - the machine went to sleep, and woke up some time later
// in those cases, we want to increment to the next run in the future
// and schedule the job for that time.
for next.Before(s.now()) {
next = j.next(next)
}
}
j.nextRun = next
j.timer = s.clock.AfterFunc(next.Sub(s.now()), func() {
// set the actual timer on the job here and listen for
// shut down events so that the job doesn't attempt to
// run if the scheduler has been shutdown.
select {
case <-s.shutdownCtx.Done():
return
case s.exec.jobsIn <- jobIn{
id: j.id,
shouldSendOut: true,
}:
}
})
// update the job with its new next and last run times and timer.
j.lastRun = s.now()
s.jobs[id] = j
}
@@ -346,7 +425,8 @@ func (s *scheduler) selectJobOutRequest(out jobOutRequest) {
close(out.outChan)
}
func (s *scheduler) selectNewJob(j internalJob) {
func (s *scheduler) selectNewJob(in newJobIn) {
j := in.job
if s.started {
next := j.startTime
if j.startImmediately {
@@ -364,7 +444,7 @@ func (s *scheduler) selectNewJob(j internalJob) {
}
id := j.id
j.timer = s.clock.AfterFunc(next.Sub(s.now()), func() {
j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() {
select {
case <-s.shutdownCtx.Done():
case s.exec.jobsIn <- jobIn{
@@ -374,10 +454,12 @@ func (s *scheduler) selectNewJob(j internalJob) {
}
})
}
j.nextRun = next
j.startTime = next
j.nextScheduled = append(j.nextScheduled, next)
}
s.jobs[j.id] = j
in.cancel()
}
func (s *scheduler) selectRemoveJobsByTags(tags []string) {
@@ -414,7 +496,7 @@ func (s *scheduler) selectStart() {
}
jobID := id
j.timer = s.clock.AfterFunc(next.Sub(s.now()), func() {
j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() {
select {
case <-s.shutdownCtx.Done():
case s.exec.jobsIn <- jobIn{
@@ -424,7 +506,8 @@ func (s *scheduler) selectStart() {
}
})
}
j.nextRun = next
j.startTime = next
j.nextScheduled = append(j.nextScheduled, next)
s.jobs[id] = j
}
select {
@@ -441,15 +524,16 @@ func (s *scheduler) selectStart() {
// -----------------------------------------------
func (s *scheduler) now() time.Time {
return s.clock.Now().In(s.location)
return s.exec.clock.Now().In(s.location)
}
func (s *scheduler) jobFromInternalJob(in internalJob) job {
return job{
id: in.id,
name: in.name,
tags: slices.Clone(in.tags),
jobOutRequest: s.jobOutRequestCh,
in.id,
in.name,
slices.Clone(in.tags),
s.jobOutRequestCh,
s.runJobRequestCh,
}
}
@@ -473,6 +557,70 @@ func (s *scheduler) NewJob(jobDefinition JobDefinition, task Task, options ...Jo
return s.addOrUpdateJob(uuid.Nil, jobDefinition, task, options)
}
func (s *scheduler) verifyInterfaceVariadic(taskFunc reflect.Value, tsk task, variadicStart int) error {
ifaceType := taskFunc.Type().In(variadicStart).Elem()
for i := variadicStart; i < len(tsk.parameters); i++ {
if !reflect.TypeOf(tsk.parameters[i]).Implements(ifaceType) {
return ErrNewJobWrongTypeOfParameters
}
}
return nil
}
func (s *scheduler) verifyVariadic(taskFunc reflect.Value, tsk task, variadicStart int) error {
if err := s.verifyNonVariadic(taskFunc, tsk, variadicStart); err != nil {
return err
}
parameterType := taskFunc.Type().In(variadicStart).Elem().Kind()
if parameterType == reflect.Interface {
return s.verifyInterfaceVariadic(taskFunc, tsk, variadicStart)
}
if parameterType == reflect.Pointer {
parameterType = reflect.Indirect(reflect.ValueOf(taskFunc.Type().In(variadicStart))).Kind()
}
for i := variadicStart; i < len(tsk.parameters); i++ {
argumentType := reflect.TypeOf(tsk.parameters[i]).Kind()
if argumentType == reflect.Interface || argumentType == reflect.Pointer {
argumentType = reflect.TypeOf(tsk.parameters[i]).Elem().Kind()
}
if argumentType != parameterType {
return ErrNewJobWrongTypeOfParameters
}
}
return nil
}
func (s *scheduler) verifyNonVariadic(taskFunc reflect.Value, tsk task, length int) error {
for i := 0; i < length; i++ {
t1 := reflect.TypeOf(tsk.parameters[i]).Kind()
if t1 == reflect.Interface || t1 == reflect.Pointer {
t1 = reflect.TypeOf(tsk.parameters[i]).Elem().Kind()
}
t2 := reflect.New(taskFunc.Type().In(i)).Elem().Kind()
if t2 == reflect.Interface || t2 == reflect.Pointer {
t2 = reflect.Indirect(reflect.ValueOf(taskFunc.Type().In(i))).Kind()
}
if t1 != t2 {
return ErrNewJobWrongTypeOfParameters
}
}
return nil
}
func (s *scheduler) verifyParameterType(taskFunc reflect.Value, tsk task) error {
isVariadic := taskFunc.Type().IsVariadic()
if isVariadic {
variadicStart := taskFunc.Type().NumIn() - 1
return s.verifyVariadic(taskFunc, tsk, variadicStart)
}
expectedParameterLength := taskFunc.Type().NumIn()
if len(tsk.parameters) != expectedParameterLength {
return ErrNewJobWrongNumberOfParameters
}
return s.verifyNonVariadic(taskFunc, tsk, expectedParameterLength)
}
func (s *scheduler) addOrUpdateJob(id uuid.UUID, definition JobDefinition, taskWrapper Task, options []JobOption) (Job, error) {
j := internalJob{}
if id == uuid.Nil {
@@ -507,23 +655,8 @@ func (s *scheduler) addOrUpdateJob(id uuid.UUID, definition JobDefinition, taskW
return nil, ErrNewJobTaskNotFunc
}
expectedParameterLength := taskFunc.Type().NumIn()
if len(tsk.parameters) != expectedParameterLength {
return nil, ErrNewJobWrongNumberOfParameters
}
for i := 0; i < expectedParameterLength; i++ {
t1 := reflect.TypeOf(tsk.parameters[i]).Kind()
if t1 == reflect.Interface || t1 == reflect.Pointer {
t1 = reflect.TypeOf(tsk.parameters[i]).Elem().Kind()
}
t2 := reflect.New(taskFunc.Type().In(i)).Elem().Kind()
if t2 == reflect.Interface || t2 == reflect.Pointer {
t2 = reflect.Indirect(reflect.ValueOf(taskFunc.Type().In(i))).Kind()
}
if t1 != t2 {
return nil, ErrNewJobWrongTypeOfParameters
}
if err := s.verifyParameterType(taskFunc, tsk); err != nil {
return nil, err
}
j.name = runtime.FuncForPC(taskFunc.Pointer()).Name()
@@ -532,34 +665,39 @@ func (s *scheduler) addOrUpdateJob(id uuid.UUID, definition JobDefinition, taskW
// apply global job options
for _, option := range s.globalJobOptions {
if err := option(&j); err != nil {
if err := option(&j, s.now()); err != nil {
return nil, err
}
}
// apply job specific options, which take precedence
for _, option := range options {
if err := option(&j); err != nil {
if err := option(&j, s.now()); err != nil {
return nil, err
}
}
if err := definition.setup(&j, s.location); err != nil {
if err := definition.setup(&j, s.location, s.exec.clock.Now()); err != nil {
return nil, err
}
newJobCtx, newJobCancel := context.WithCancel(context.Background())
select {
case <-s.shutdownCtx.Done():
case s.newJobCh <- j:
case s.newJobCh <- newJobIn{
ctx: newJobCtx,
cancel: newJobCancel,
job: j,
}:
}
return &job{
id: j.id,
name: j.name,
tags: slices.Clone(j.tags),
jobOutRequest: s.jobOutRequestCh,
runJobRequest: s.runJobRequestCh,
}, nil
select {
case <-newJobCtx.Done():
case <-s.shutdownCtx.Done():
}
out := s.jobFromInternalJob(j)
return &out, nil
}
func (s *scheduler) RemoveByTags(tags ...string) {
@@ -618,6 +756,13 @@ func (s *scheduler) Update(id uuid.UUID, jobDefinition JobDefinition, task Task,
return s.addOrUpdateJob(id, jobDefinition, task, options)
}
func (s *scheduler) JobsWaitingInQueue() int {
if s.exec.limitMode != nil && s.exec.limitMode.mode == LimitModeWait {
return len(s.exec.limitMode.in)
}
return 0
}
// -----------------------------------------------
// -----------------------------------------------
// ------------- Scheduler Options ---------------
@@ -635,7 +780,7 @@ func WithClock(clock clockwork.Clock) SchedulerOption {
if clock == nil {
return ErrWithClockNil
}
s.clock = clock
s.exec.clock = clock
return nil
}
}
@@ -718,6 +863,14 @@ const (
// WithLimitConcurrentJobs sets the limit and mode to be used by the
// Scheduler for limiting the number of jobs that may be running at
// a given time.
//
// Note: the limit mode selected for WithLimitConcurrentJobs takes initial
// precedence in the event you are also running a limit mode at the job level
// using WithSingletonMode.
//
// Warning: a single time consuming job can dominate your limit in the event
// you are running both the scheduler limit WithLimitConcurrentJobs(1, LimitModeWait)
// and a job limit WithSingletonMode(LimitModeReschedule).
func WithLimitConcurrentJobs(limit uint, mode LimitMode) SchedulerOption {
return func(s *scheduler) error {
if limit == 0 {
@@ -774,3 +927,14 @@ func WithStopTimeout(timeout time.Duration) SchedulerOption {
return nil
}
}
// WithMonitor sets the metrics provider to be used by the Scheduler.
func WithMonitor(monitor Monitor) SchedulerOption {
return func(s *scheduler) error {
if monitor == nil {
return ErrWithMonitorNil
}
s.exec.monitor = monitor
return nil
}
}

View File

@@ -44,18 +44,12 @@ func requestJob(id uuid.UUID, ch chan jobOutRequest) *internalJob {
func requestJobCtx(ctx context.Context, id uuid.UUID, ch chan jobOutRequest) *internalJob {
resp := make(chan internalJob, 1)
select {
case <-ctx.Done():
return nil
default:
}
select {
case ch <- jobOutRequest{
id: id,
outChan: resp,
}:
default:
case <-ctx.Done():
return nil
}
var j internalJob
@@ -94,12 +88,14 @@ func convertAtTimesToDateTime(atTimes AtTimes, location *time.Location) ([]time.
}
atTimesDate = append(atTimesDate, at.time(location))
}
slices.SortStableFunc(atTimesDate, func(a, b time.Time) int {
return a.Compare(b)
})
slices.SortStableFunc(atTimesDate, ascendingTime)
return atTimesDate, nil
}
func ascendingTime(a, b time.Time) int {
return a.Compare(b)
}
type waitGroupWithMutex struct {
wg sync.WaitGroup
mu sync.Mutex

View File

@@ -1,5 +1,18 @@
# Changelog
## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16)
### Features
* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3))
### Bug Fixes
* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06))
* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6))
## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12)

View File

@@ -17,6 +17,12 @@ var (
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
Nil UUID // empty UUID, all zeros
// The Max UUID is special form of UUID that is specified to have all 128 bits set to 1.
Max = UUID{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
}
)
// NewHash returns a new UUID derived from the hash of space concatenated with

View File

@@ -44,7 +44,7 @@ func NewV7FromReader(r io.Reader) (UUID, error) {
// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
// uuid[8] already has the right version number (Variant is 10)
// see function NewV7 and NewV7FromReader
// see function NewV7 and NewV7FromReader
func makeV7(uuid []byte) {
/*
0 1 2 3
@@ -52,7 +52,7 @@ func makeV7(uuid []byte) {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a |
| unix_ts_ms | ver | rand_a (12 bit seq) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -61,7 +61,7 @@ func makeV7(uuid []byte) {
*/
_ = uuid[15] // bounds check
t := timeNow().UnixMilli()
t, s := getV7Time()
uuid[0] = byte(t >> 40)
uuid[1] = byte(t >> 32)
@@ -70,6 +70,35 @@ func makeV7(uuid []byte) {
uuid[4] = byte(t >> 8)
uuid[5] = byte(t)
uuid[6] = 0x70 | (uuid[6] & 0x0F)
// uuid[8] has already has right version
uuid[6] = 0x70 | (0x0F & byte(s>>8))
uuid[7] = byte(s)
}
// lastV7time is the last time we returned stored as:
//
// 52 bits of time in milliseconds since epoch
// 12 bits of (fractional nanoseconds) >> 8
var lastV7time int64
const nanoPerMilli = 1000000
// getV7Time returns the time in milliseconds and nanoseconds / 256.
// The returned (milli << 12 + seq) is guarenteed to be greater than
// (milli << 12 + seq) returned by any previous call to getV7Time.
func getV7Time() (milli, seq int64) {
timeMu.Lock()
defer timeMu.Unlock()
nano := timeNow().UnixNano()
milli = nano / nanoPerMilli
// Sequence number is between 0 and 3906 (nanoPerMilli>>8)
seq = (nano - milli*nanoPerMilli) >> 8
now := milli<<12 + seq
if now <= lastV7time {
now = lastV7time + 1
milli = now >> 12
seq = now & 0xfff
}
lastV7time = now
return milli, seq
}

View File

@@ -35,8 +35,6 @@ import (
const version = 32
var defaultAddr = fmt.Sprintf("/run/user/%d/pulse/native", os.Getuid())
type packetResponse struct {
buff *bytes.Buffer
err error
@@ -67,7 +65,11 @@ type Client struct {
// NewClient establishes a connection to the PulseAudio server.
func NewClient(addressArr ...string) (*Client, error) {
if len(addressArr) < 1 {
addressArr = []string{defaultAddr}
xdgRuntimeDir, ok := os.LookupEnv("XDG_RUNTIME_DIR")
if !ok {
xdgRuntimeDir = fmt.Sprintf("/run/user/%d", os.Getuid())
}
addressArr = []string{fmt.Sprintf("%s/pulse/native", xdgRuntimeDir)}
}
conn, err := net.Dial("unix", addressArr[0])

View File

@@ -456,6 +456,18 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
Reason: "not a Float32",
}
}
case float64:
switch f.Kind() {
case reflect.Float32, reflect.Float64:
f.SetFloat(val)
default:
return &ErrFieldMismatch{
StructType: of.Type(),
FieldName: n,
Reason: "not a Float64",
}
}
default:
if f.Kind() == reflect.Slice {
switch f.Type().Elem().Kind() {

4
vendor/golang.org/x/exp/LICENSE generated vendored
View File

@@ -1,4 +1,4 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

View File

@@ -209,25 +209,37 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
return s
}
// Delete removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if s[i:j] is not a valid slice of s.
// Delete is O(len(s)-j), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those
// elements contain pointers you might consider zeroing those elements so that
// objects they reference can be garbage collected.
func Delete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j] // bounds check
// clearSlice sets all elements up to the length of s to the zero value of E.
// We may use the builtin clear func instead, and remove clearSlice, when upgrading
// to Go 1.21+.
func clearSlice[S ~[]E, E any](s S) {
var zero E
for i := range s {
s[i] = zero
}
}
return append(s[:i], s[j:]...)
// Delete removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
func Delete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j:len(s)] // bounds check
if i == j {
return s
}
oldlen := len(s)
s = append(s[:i], s[j:]...)
clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
return s
}
// DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice.
// When DeleteFunc removes m elements, it might not modify the elements
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage
// collected.
// DeleteFunc zeroes the elements between the new length and the original length.
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i := IndexFunc(s, del)
if i == -1 {
@@ -240,11 +252,13 @@ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i++
}
}
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i]
}
// Replace replaces the elements s[i:j] by the given v, and returns the
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
_ = s[i:j] // verify that i:j is a valid subslice
@@ -272,6 +286,7 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
if i+len(v) != j {
copy(r[i+len(v):], s[j:])
}
clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
return r
}
@@ -345,9 +360,7 @@ func Clone[S ~[]E, E any](s S) S {
// This is like the uniq command found on Unix.
// Compact modifies the contents of the slice s and returns the modified slice,
// which may have a smaller length.
// When Compact discards m elements in total, it might not modify the elements
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage collected.
// Compact zeroes the elements between the new length and the original length.
func Compact[S ~[]E, E comparable](s S) S {
if len(s) < 2 {
return s
@@ -361,11 +374,13 @@ func Compact[S ~[]E, E comparable](s S) S {
i++
}
}
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i]
}
// CompactFunc is like [Compact] but uses an equality function to compare elements.
// For runs of elements that compare equal, CompactFunc keeps the first one.
// CompactFunc zeroes the elements between the new length and the original length.
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
if len(s) < 2 {
return s
@@ -379,6 +394,7 @@ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
i++
}
}
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i]
}

View File

@@ -22,10 +22,12 @@ func Sort[S ~[]E, E constraints.Ordered](x S) {
// SortFunc sorts the slice x in ascending order as determined by the cmp
// function. This sort is not guaranteed to be stable.
// cmp(a, b) should return a negative number when a < b, a positive number when
// a > b and zero when a == b.
// a > b and zero when a == b or when a is not comparable to b in the sense
// of the formal definition of Strict Weak Ordering.
//
// SortFunc requires that cmp is a strict weak ordering.
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
// To indicate 'uncomparable', return 0 from the function.
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
n := len(x)
pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)

4
vendor/golang.org/x/sys/LICENSE generated vendored
View File

@@ -1,4 +1,4 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
package unix

View File

@@ -9,9 +9,11 @@
#define PSALAA 1208(R0)
#define GTAB64(x) 80(x)
#define LCA64(x) 88(x)
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
#define CAA(x) 8(x)
#define EDCHPXV(x) 1016(x) // in the CAA
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
#define CEECAATHDID(x) 976(x) // in the CAA
#define EDCHPXV(x) 1016(x) // in the CAA
#define GOCB(x) 1104(x) // in the CAA
// SS_*, where x=SAVSTACK_ASYNC
#define SS_LE(x) 0(x)
@@ -19,394 +21,125 @@
#define SS_ERRNO(x) 16(x)
#define SS_ERRNOJR(x) 20(x)
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
// Function Descriptor Offsets
#define __errno 0x156*16
#define __err2ad 0x16C*16
TEXT ·clearErrno(SB),NOSPLIT,$0-0
BL addrerrno<>(SB)
MOVD $0, 0(R3)
// Call Instructions
#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
DATA zosLibVec<>(SB)/8, $0
GLOBL zosLibVec<>(SB), NOPTR, $8
TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD CAA(R8), R8
MOVD EDCHPXV(R8), R8
MOVD R8, zosLibVec<>(SB)
RET
TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
MOVD zosLibVec<>(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·clearErrno(SB), NOSPLIT, $0-0
BL addrerrno<>(SB)
MOVD $0, 0(R3)
RET
// Returns the address of errno in R3.
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get __errno FuncDesc.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
ADD $(0x156*16), R9
LMG 0(R9), R5, R6
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
ADD $(__errno), R9
LMG 0(R9), R5, R6
// Switch to saved LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Call __errno function.
LE_CALL
NOPH
// Switch back to Go stack.
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
RET
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
BL runtime·entersyscall(SB)
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+32(FP)
MOVD R0, r2+40(FP)
MOVD R0, err+48(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL addrerrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+48(FP)
done:
BL runtime·exitsyscall(SB)
RET
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+32(FP)
MOVD R0, r2+40(FP)
MOVD R0, err+48(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL addrerrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+48(FP)
done:
RET
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
BL runtime·entersyscall(SB)
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Fill in parameter list.
MOVD a4+32(FP), R12
MOVD R12, (2176+24)(R4)
MOVD a5+40(FP), R12
MOVD R12, (2176+32)(R4)
MOVD a6+48(FP), R12
MOVD R12, (2176+40)(R4)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+56(FP)
MOVD R0, r2+64(FP)
MOVD R0, err+72(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL addrerrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+72(FP)
done:
BL runtime·exitsyscall(SB)
RET
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Fill in parameter list.
MOVD a4+32(FP), R12
MOVD R12, (2176+24)(R4)
MOVD a5+40(FP), R12
MOVD R12, (2176+32)(R4)
MOVD a6+48(FP), R12
MOVD R12, (2176+40)(R4)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+56(FP)
MOVD R0, r2+64(FP)
MOVD R0, err+72(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL ·rrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+72(FP)
done:
RET
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
BL runtime·entersyscall(SB)
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Fill in parameter list.
MOVD a4+32(FP), R12
MOVD R12, (2176+24)(R4)
MOVD a5+40(FP), R12
MOVD R12, (2176+32)(R4)
MOVD a6+48(FP), R12
MOVD R12, (2176+40)(R4)
MOVD a7+56(FP), R12
MOVD R12, (2176+48)(R4)
MOVD a8+64(FP), R12
MOVD R12, (2176+56)(R4)
MOVD a9+72(FP), R12
MOVD R12, (2176+64)(R4)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+80(FP)
MOVD R0, r2+88(FP)
MOVD R0, err+96(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL addrerrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+96(FP)
done:
BL runtime·exitsyscall(SB)
RET
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
MOVD a1+8(FP), R1
MOVD a2+16(FP), R2
MOVD a3+24(FP), R3
// Get library control area (LCA).
MOVW PSALAA, R8
MOVD LCA64(R8), R8
// Get function.
MOVD CAA(R8), R9
MOVD EDCHPXV(R9), R9
MOVD trap+0(FP), R5
SLD $4, R5
ADD R5, R9
LMG 0(R9), R5, R6
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R4
MOVD $0, 0(R9)
// Fill in parameter list.
MOVD a4+32(FP), R12
MOVD R12, (2176+24)(R4)
MOVD a5+40(FP), R12
MOVD R12, (2176+32)(R4)
MOVD a6+48(FP), R12
MOVD R12, (2176+40)(R4)
MOVD a7+56(FP), R12
MOVD R12, (2176+48)(R4)
MOVD a8+64(FP), R12
MOVD R12, (2176+56)(R4)
MOVD a9+72(FP), R12
MOVD R12, (2176+64)(R4)
// Call function.
LE_CALL
NOPH
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
MOVD R3, r1+80(FP)
MOVD R0, r2+88(FP)
MOVD R0, err+96(FP)
MOVW R3, R4
CMP R4, $-1
BNE done
BL addrerrno<>(SB)
MOVWZ 0(R3), R3
MOVD R3, err+96(FP)
done:
XOR R0, R0 // Restore R0 to $0.
MOVD R4, 0(R9) // Save stack pointer.
RET
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
TEXT ·svcCall(SB),NOSPLIT,$0
BL runtime·save_g(SB) // Save g and stack pointer
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD SAVSTACK_ASYNC(R8), R9
MOVD R15, 0(R9)
TEXT ·svcCall(SB), NOSPLIT, $0
BL runtime·save_g(SB) // Save g and stack pointer
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD SAVSTACK_ASYNC(R8), R9
MOVD R15, 0(R9)
MOVD argv+8(FP), R1 // Move function arguments into registers
MOVD dsa+16(FP), g
MOVD fnptr+0(FP), R15
MOVD argv+8(FP), R1 // Move function arguments into registers
MOVD dsa+16(FP), g
MOVD fnptr+0(FP), R15
BYTE $0x0D // Branch to function
BYTE $0xEF
BYTE $0x0D // Branch to function
BYTE $0xEF
BL runtime·load_g(SB) // Restore g and stack pointer
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R15
BL runtime·load_g(SB) // Restore g and stack pointer
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD SAVSTACK_ASYNC(R8), R9
MOVD 0(R9), R15
RET
// func svcLoad(name *byte) unsafe.Pointer
TEXT ·svcLoad(SB),NOSPLIT,$0
MOVD R15, R2 // Save go stack pointer
MOVD name+0(FP), R0 // Move SVC args into registers
MOVD $0x80000000, R1
MOVD $0, R15
BYTE $0x0A // SVC 08 LOAD
BYTE $0x08
MOVW R15, R3 // Save return code from SVC
MOVD R2, R15 // Restore go stack pointer
CMP R3, $0 // Check SVC return code
BNE error
TEXT ·svcLoad(SB), NOSPLIT, $0
MOVD R15, R2 // Save go stack pointer
MOVD name+0(FP), R0 // Move SVC args into registers
MOVD $0x80000000, R1
MOVD $0, R15
SVC_LOAD
MOVW R15, R3 // Save return code from SVC
MOVD R2, R15 // Restore go stack pointer
CMP R3, $0 // Check SVC return code
BNE error
MOVD $-2, R3 // Reset last bit of entry point to zero
AND R0, R3
MOVD R3, addr+8(FP) // Return entry point returned by SVC
CMP R0, R3 // Check if last bit of entry point was set
BNE done
MOVD $-2, R3 // Reset last bit of entry point to zero
AND R0, R3
MOVD R3, ret+8(FP) // Return entry point returned by SVC
CMP R0, R3 // Check if last bit of entry point was set
BNE done
MOVD R15, R2 // Save go stack pointer
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
BYTE $0x0A // SVC 09 DELETE
BYTE $0x09
MOVD R2, R15 // Restore go stack pointer
MOVD R15, R2 // Save go stack pointer
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
SVC_DELETE
MOVD R2, R15 // Restore go stack pointer
error:
MOVD $0, addr+8(FP) // Return 0 on failure
MOVD $0, ret+8(FP) // Return 0 on failure
done:
XOR R0, R0 // Reset r0 to 0
XOR R0, R0 // Reset r0 to 0
RET
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
TEXT ·svcUnload(SB),NOSPLIT,$0
MOVD R15, R2 // Save go stack pointer
MOVD name+0(FP), R0 // Move SVC args into registers
MOVD addr+8(FP), R15
BYTE $0x0A // SVC 09
BYTE $0x09
XOR R0, R0 // Reset r0 to 0
MOVD R15, R1 // Save SVC return code
MOVD R2, R15 // Restore go stack pointer
MOVD R1, rc+0(FP) // Return SVC return code
TEXT ·svcUnload(SB), NOSPLIT, $0
MOVD R15, R2 // Save go stack pointer
MOVD name+0(FP), R0 // Move SVC args into registers
MOVD fnptr+8(FP), R15
SVC_DELETE
XOR R0, R0 // Reset r0 to 0
MOVD R15, R1 // Save SVC return code
MOVD R2, R15 // Restore go stack pointer
MOVD R1, ret+16(FP) // Return SVC return code
RET
// func gettid() uint64
@@ -417,7 +150,233 @@ TEXT ·gettid(SB), NOSPLIT, $0
// Get CEECAATHDID
MOVD CAA(R8), R9
MOVD 0x3D0(R9), R9
MOVD CEECAATHDID(R9), R9
MOVD R9, ret+0(FP)
RET
//
// Call LE function, if the return is -1
// errno and errno2 is retrieved
//
TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD CAA(R8), R9
MOVD g, GOCB(R9)
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
MOVD parms_base+8(FP), R7 // R7 -> argument array
MOVD parms_len+16(FP), R8 // R8 number of arguments
// arg 1 ---> R1
CMP R8, $0
BEQ docall
SUB $1, R8
MOVD 0(R7), R1
// arg 2 ---> R2
CMP R8, $0
BEQ docall
SUB $1, R8
ADD $8, R7
MOVD 0(R7), R2
// arg 3 --> R3
CMP R8, $0
BEQ docall
SUB $1, R8
ADD $8, R7
MOVD 0(R7), R3
CMP R8, $0
BEQ docall
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
repeat:
ADD $8, R7
MOVD 0(R7), R0 // advance arg pointer by 8 byte
ADD $8, R6 // advance LE argument address by 8 byte
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
SUB $1, R8
CMP R8, $0
BNE repeat
docall:
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
LMG 0(R8), R5, R6
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
LE_CALL // balr R7, R6 (return #1)
NOPH
MOVD R3, ret+32(FP)
CMP R3, $-1 // compare result to -1
BNE done
// retrieve errno and errno2
MOVD zosLibVec<>(SB), R8
ADD $(__errno), R8
LMG 0(R8), R5, R6
LE_CALL // balr R7, R6 __errno (return #3)
NOPH
MOVWZ 0(R3), R3
MOVD R3, err+48(FP)
MOVD zosLibVec<>(SB), R8
ADD $(__err2ad), R8
LMG 0(R8), R5, R6
LE_CALL // balr R7, R6 __err2ad (return #2)
NOPH
MOVW (R3), R2 // retrieve errno2
MOVD R2, errno2+40(FP) // store in return area
done:
MOVD R4, 0(R9) // Save stack pointer.
RET
//
// Call LE function, if the return is 0
// errno and errno2 is retrieved
//
TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
MOVW PSALAA, R8
MOVD LCA64(R8), R8
MOVD CAA(R8), R9
MOVD g, GOCB(R9)
// Restore LE stack.
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
MOVD parms_base+8(FP), R7 // R7 -> argument array
MOVD parms_len+16(FP), R8 // R8 number of arguments
// arg 1 ---> R1
CMP R8, $0
BEQ docall
SUB $1, R8
MOVD 0(R7), R1
// arg 2 ---> R2
CMP R8, $0
BEQ docall
SUB $1, R8
ADD $8, R7
MOVD 0(R7), R2
// arg 3 --> R3
CMP R8, $0
BEQ docall
SUB $1, R8
ADD $8, R7
MOVD 0(R7), R3
CMP R8, $0
BEQ docall
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
repeat:
ADD $8, R7
MOVD 0(R7), R0 // advance arg pointer by 8 byte
ADD $8, R6 // advance LE argument address by 8 byte
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
SUB $1, R8
CMP R8, $0
BNE repeat
docall:
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
LMG 0(R8), R5, R6
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
LE_CALL // balr R7, R6 (return #1)
NOPH
MOVD R3, ret+32(FP)
CMP R3, $0 // compare result to 0
BNE done
// retrieve errno and errno2
MOVD zosLibVec<>(SB), R8
ADD $(__errno), R8
LMG 0(R8), R5, R6
LE_CALL // balr R7, R6 __errno (return #3)
NOPH
MOVWZ 0(R3), R3
MOVD R3, err+48(FP)
MOVD zosLibVec<>(SB), R8
ADD $(__err2ad), R8
LMG 0(R8), R5, R6
LE_CALL // balr R7, R6 __err2ad (return #2)
NOPH
MOVW (R3), R2 // retrieve errno2
MOVD R2, errno2+40(FP) // store in return area
XOR R2, R2
MOVWZ R2, (R3) // clear errno2
done:
MOVD R4, 0(R9) // Save stack pointer.
RET
//
// function to test if a pointer can be safely dereferenced (content read)
// return 0 for succces
//
TEXT ·ptrtest(SB), NOSPLIT, $0-16
MOVD arg+0(FP), R10 // test pointer in R10
// set up R2 to point to CEECAADMC
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
// set up R5 to point to the "shunt" path which set 1 to R3 (failure)
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
// if r3 is not zero (failed) then branch to finish
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
// stomic store shunt address in R5 into CEECAADMC
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
// now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
// finish here, restore 0 into CEECAADMC
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
MOVD R3, ret+8(FP) // result in R3
RET
//
// function to test if a untptr can be loaded from a pointer
// return 1: the 8-byte content
// 2: 0 for success, 1 for failure
//
// func safeload(ptr uintptr) ( value uintptr, error uintptr)
TEXT ·safeload(SB), NOSPLIT, $0-24
MOVD ptr+0(FP), R10 // test pointer in R10
MOVD $0x0, R6
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
MOVD R6, value+8(FP) // result in R6
MOVD R3, error+16(FP) // error in R3
RET

657
vendor/golang.org/x/sys/unix/bpxsvc_zos.go generated vendored Normal file
View File

@@ -0,0 +1,657 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build zos
package unix
import (
"bytes"
"fmt"
"unsafe"
)
//go:noescape
func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
//go:noescape
func A2e([]byte)
//go:noescape
func E2a([]byte)
const (
BPX4STA = 192 // stat
BPX4FST = 104 // fstat
BPX4LST = 132 // lstat
BPX4OPN = 156 // open
BPX4CLO = 72 // close
BPX4CHR = 500 // chattr
BPX4FCR = 504 // fchattr
BPX4LCR = 1180 // lchattr
BPX4CTW = 492 // cond_timed_wait
BPX4GTH = 1056 // __getthent
BPX4PTQ = 412 // pthread_quiesc
BPX4PTR = 320 // ptrace
)
const (
//options
//byte1
BPX_OPNFHIGH = 0x80
//byte2
BPX_OPNFEXEC = 0x80
//byte3
BPX_O_NOLARGEFILE = 0x08
BPX_O_LARGEFILE = 0x04
BPX_O_ASYNCSIG = 0x02
BPX_O_SYNC = 0x01
//byte4
BPX_O_CREXCL = 0xc0
BPX_O_CREAT = 0x80
BPX_O_EXCL = 0x40
BPX_O_NOCTTY = 0x20
BPX_O_TRUNC = 0x10
BPX_O_APPEND = 0x08
BPX_O_NONBLOCK = 0x04
BPX_FNDELAY = 0x04
BPX_O_RDWR = 0x03
BPX_O_RDONLY = 0x02
BPX_O_WRONLY = 0x01
BPX_O_ACCMODE = 0x03
BPX_O_GETFL = 0x0f
//mode
// byte1 (file type)
BPX_FT_DIR = 1
BPX_FT_CHARSPEC = 2
BPX_FT_REGFILE = 3
BPX_FT_FIFO = 4
BPX_FT_SYMLINK = 5
BPX_FT_SOCKET = 6
//byte3
BPX_S_ISUID = 0x08
BPX_S_ISGID = 0x04
BPX_S_ISVTX = 0x02
BPX_S_IRWXU1 = 0x01
BPX_S_IRUSR = 0x01
//byte4
BPX_S_IRWXU2 = 0xc0
BPX_S_IWUSR = 0x80
BPX_S_IXUSR = 0x40
BPX_S_IRWXG = 0x38
BPX_S_IRGRP = 0x20
BPX_S_IWGRP = 0x10
BPX_S_IXGRP = 0x08
BPX_S_IRWXOX = 0x07
BPX_S_IROTH = 0x04
BPX_S_IWOTH = 0x02
BPX_S_IXOTH = 0x01
CW_INTRPT = 1
CW_CONDVAR = 32
CW_TIMEOUT = 64
PGTHA_NEXT = 2
PGTHA_CURRENT = 1
PGTHA_FIRST = 0
PGTHA_LAST = 3
PGTHA_PROCESS = 0x80
PGTHA_CONTTY = 0x40
PGTHA_PATH = 0x20
PGTHA_COMMAND = 0x10
PGTHA_FILEDATA = 0x08
PGTHA_THREAD = 0x04
PGTHA_PTAG = 0x02
PGTHA_COMMANDLONG = 0x01
PGTHA_THREADFAST = 0x80
PGTHA_FILEPATH = 0x40
PGTHA_THDSIGMASK = 0x20
// thread quiece mode
QUIESCE_TERM int32 = 1
QUIESCE_FORCE int32 = 2
QUIESCE_QUERY int32 = 3
QUIESCE_FREEZE int32 = 4
QUIESCE_UNFREEZE int32 = 5
FREEZE_THIS_THREAD int32 = 6
FREEZE_EXIT int32 = 8
QUIESCE_SRB int32 = 9
)
type Pgtha struct {
Pid uint32 // 0
Tid0 uint32 // 4
Tid1 uint32
Accesspid byte // C
Accesstid byte // D
Accessasid uint16 // E
Loginname [8]byte // 10
Flag1 byte // 18
Flag1b2 byte // 19
}
type Bpxystat_t struct { // DSECT BPXYSTAT
St_id [4]uint8 // 0
St_length uint16 // 0x4
St_version uint16 // 0x6
St_mode uint32 // 0x8
St_ino uint32 // 0xc
St_dev uint32 // 0x10
St_nlink uint32 // 0x14
St_uid uint32 // 0x18
St_gid uint32 // 0x1c
St_size uint64 // 0x20
St_atime uint32 // 0x28
St_mtime uint32 // 0x2c
St_ctime uint32 // 0x30
St_rdev uint32 // 0x34
St_auditoraudit uint32 // 0x38
St_useraudit uint32 // 0x3c
St_blksize uint32 // 0x40
St_createtime uint32 // 0x44
St_auditid [4]uint32 // 0x48
St_res01 uint32 // 0x58
Ft_ccsid uint16 // 0x5c
Ft_flags uint16 // 0x5e
St_res01a [2]uint32 // 0x60
St_res02 uint32 // 0x68
St_blocks uint32 // 0x6c
St_opaque [3]uint8 // 0x70
St_visible uint8 // 0x73
St_reftime uint32 // 0x74
St_fid uint64 // 0x78
St_filefmt uint8 // 0x80
St_fspflag2 uint8 // 0x81
St_res03 [2]uint8 // 0x82
St_ctimemsec uint32 // 0x84
St_seclabel [8]uint8 // 0x88
St_res04 [4]uint8 // 0x90
// end of version 1
_ uint32 // 0x94
St_atime64 uint64 // 0x98
St_mtime64 uint64 // 0xa0
St_ctime64 uint64 // 0xa8
St_createtime64 uint64 // 0xb0
St_reftime64 uint64 // 0xb8
_ uint64 // 0xc0
St_res05 [16]uint8 // 0xc8
// end of version 2
}
type BpxFilestatus struct {
Oflag1 byte
Oflag2 byte
Oflag3 byte
Oflag4 byte
}
type BpxMode struct {
Ftype byte
Mode1 byte
Mode2 byte
Mode3 byte
}
// Thr attribute structure for extended attributes
type Bpxyatt_t struct { // DSECT BPXYATT
Att_id [4]uint8
Att_version uint16
Att_res01 [2]uint8
Att_setflags1 uint8
Att_setflags2 uint8
Att_setflags3 uint8
Att_setflags4 uint8
Att_mode uint32
Att_uid uint32
Att_gid uint32
Att_opaquemask [3]uint8
Att_visblmaskres uint8
Att_opaque [3]uint8
Att_visibleres uint8
Att_size_h uint32
Att_size_l uint32
Att_atime uint32
Att_mtime uint32
Att_auditoraudit uint32
Att_useraudit uint32
Att_ctime uint32
Att_reftime uint32
// end of version 1
Att_filefmt uint8
Att_res02 [3]uint8
Att_filetag uint32
Att_res03 [8]uint8
// end of version 2
Att_atime64 uint64
Att_mtime64 uint64
Att_ctime64 uint64
Att_reftime64 uint64
Att_seclabel [8]uint8
Att_ver3res02 [8]uint8
// end of version 3
}
func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) {
if len(name) < 1024 {
var namebuf [1024]byte
sz := int32(copy(namebuf[:], name))
A2e(namebuf[:sz])
var parms [7]unsafe.Pointer
parms[0] = unsafe.Pointer(&sz)
parms[1] = unsafe.Pointer(&namebuf[0])
parms[2] = unsafe.Pointer(options)
parms[3] = unsafe.Pointer(mode)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4OPN)
return rv, rc, rn
}
return -1, -1, -1
}
func BpxClose(fd int32) (rv int32, rc int32, rn int32) {
var parms [4]unsafe.Pointer
parms[0] = unsafe.Pointer(&fd)
parms[1] = unsafe.Pointer(&rv)
parms[2] = unsafe.Pointer(&rc)
parms[3] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4CLO)
return rv, rc, rn
}
func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
st.St_version = 2
stat_sz := uint32(unsafe.Sizeof(*st))
var parms [6]unsafe.Pointer
parms[0] = unsafe.Pointer(&fd)
parms[1] = unsafe.Pointer(&stat_sz)
parms[2] = unsafe.Pointer(st)
parms[3] = unsafe.Pointer(&rv)
parms[4] = unsafe.Pointer(&rc)
parms[5] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4FST)
return rv, rc, rn
}
func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
if len(name) < 1024 {
var namebuf [1024]byte
sz := int32(copy(namebuf[:], name))
A2e(namebuf[:sz])
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
st.St_version = 2
stat_sz := uint32(unsafe.Sizeof(*st))
var parms [7]unsafe.Pointer
parms[0] = unsafe.Pointer(&sz)
parms[1] = unsafe.Pointer(&namebuf[0])
parms[2] = unsafe.Pointer(&stat_sz)
parms[3] = unsafe.Pointer(st)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4STA)
return rv, rc, rn
}
return -1, -1, -1
}
func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
if len(name) < 1024 {
var namebuf [1024]byte
sz := int32(copy(namebuf[:], name))
A2e(namebuf[:sz])
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
st.St_version = 2
stat_sz := uint32(unsafe.Sizeof(*st))
var parms [7]unsafe.Pointer
parms[0] = unsafe.Pointer(&sz)
parms[1] = unsafe.Pointer(&namebuf[0])
parms[2] = unsafe.Pointer(&stat_sz)
parms[3] = unsafe.Pointer(st)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4LST)
return rv, rc, rn
}
return -1, -1, -1
}
func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
if len(path) >= 1024 {
return -1, -1, -1
}
var namebuf [1024]byte
sz := int32(copy(namebuf[:], path))
A2e(namebuf[:sz])
attr_sz := uint32(unsafe.Sizeof(*attr))
var parms [7]unsafe.Pointer
parms[0] = unsafe.Pointer(&sz)
parms[1] = unsafe.Pointer(&namebuf[0])
parms[2] = unsafe.Pointer(&attr_sz)
parms[3] = unsafe.Pointer(attr)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4CHR)
return rv, rc, rn
}
func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
if len(path) >= 1024 {
return -1, -1, -1
}
var namebuf [1024]byte
sz := int32(copy(namebuf[:], path))
A2e(namebuf[:sz])
attr_sz := uint32(unsafe.Sizeof(*attr))
var parms [7]unsafe.Pointer
parms[0] = unsafe.Pointer(&sz)
parms[1] = unsafe.Pointer(&namebuf[0])
parms[2] = unsafe.Pointer(&attr_sz)
parms[3] = unsafe.Pointer(attr)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4LCR)
return rv, rc, rn
}
func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
attr_sz := uint32(unsafe.Sizeof(*attr))
var parms [6]unsafe.Pointer
parms[0] = unsafe.Pointer(&fd)
parms[1] = unsafe.Pointer(&attr_sz)
parms[2] = unsafe.Pointer(attr)
parms[3] = unsafe.Pointer(&rv)
parms[4] = unsafe.Pointer(&rc)
parms[5] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4FCR)
return rv, rc, rn
}
func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) {
var parms [8]unsafe.Pointer
parms[0] = unsafe.Pointer(&sec)
parms[1] = unsafe.Pointer(&nsec)
parms[2] = unsafe.Pointer(&events)
parms[3] = unsafe.Pointer(secrem)
parms[4] = unsafe.Pointer(nsecrem)
parms[5] = unsafe.Pointer(&rv)
parms[6] = unsafe.Pointer(&rc)
parms[7] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4CTW)
return rv, rc, rn
}
func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) {
var parms [7]unsafe.Pointer
inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte
parms[0] = unsafe.Pointer(&inlen)
parms[1] = unsafe.Pointer(&in)
parms[2] = unsafe.Pointer(outlen)
parms[3] = unsafe.Pointer(&out)
parms[4] = unsafe.Pointer(&rv)
parms[5] = unsafe.Pointer(&rc)
parms[6] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4GTH)
return rv, rc, rn
}
func ZosJobname() (jobname string, err error) {
var pgtha Pgtha
pgtha.Pid = uint32(Getpid())
pgtha.Accesspid = PGTHA_CURRENT
pgtha.Flag1 = PGTHA_PROCESS
var out [256]byte
var outlen uint32
outlen = 256
rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0]))
if rv == 0 {
gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic
ix := bytes.Index(out[:], gthc)
if ix == -1 {
err = fmt.Errorf("BPX4GTH: gthc return data not found")
return
}
jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80
E2a(jn)
jobname = string(bytes.TrimRight(jn, " "))
} else {
err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn)
}
return
}
func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) {
var userdata [8]byte
var parms [5]unsafe.Pointer
copy(userdata[:], data+" ")
A2e(userdata[:])
parms[0] = unsafe.Pointer(&code)
parms[1] = unsafe.Pointer(&userdata[0])
parms[2] = unsafe.Pointer(&rv)
parms[3] = unsafe.Pointer(&rc)
parms[4] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4PTQ)
return rv, rc, rn
}
const (
PT_TRACE_ME = 0 // Debug this process
PT_READ_I = 1 // Read a full word
PT_READ_D = 2 // Read a full word
PT_READ_U = 3 // Read control info
PT_WRITE_I = 4 //Write a full word
PT_WRITE_D = 5 //Write a full word
PT_CONTINUE = 7 //Continue the process
PT_KILL = 8 //Terminate the process
PT_READ_GPR = 11 // Read GPR, CR, PSW
PT_READ_FPR = 12 // Read FPR
PT_READ_VR = 13 // Read VR
PT_WRITE_GPR = 14 // Write GPR, CR, PSW
PT_WRITE_FPR = 15 // Write FPR
PT_WRITE_VR = 16 // Write VR
PT_READ_BLOCK = 17 // Read storage
PT_WRITE_BLOCK = 19 // Write storage
PT_READ_GPRH = 20 // Read GPRH
PT_WRITE_GPRH = 21 // Write GPRH
PT_REGHSET = 22 // Read all GPRHs
PT_ATTACH = 30 // Attach to a process
PT_DETACH = 31 // Detach from a process
PT_REGSET = 32 // Read all GPRs
PT_REATTACH = 33 // Reattach to a process
PT_LDINFO = 34 // Read loader info
PT_MULTI = 35 // Multi process mode
PT_LD64INFO = 36 // RMODE64 Info Area
PT_BLOCKREQ = 40 // Block request
PT_THREAD_INFO = 60 // Read thread info
PT_THREAD_MODIFY = 61
PT_THREAD_READ_FOCUS = 62
PT_THREAD_WRITE_FOCUS = 63
PT_THREAD_HOLD = 64
PT_THREAD_SIGNAL = 65
PT_EXPLAIN = 66
PT_EVENTS = 67
PT_THREAD_INFO_EXTENDED = 68
PT_REATTACH2 = 71
PT_CAPTURE = 72
PT_UNCAPTURE = 73
PT_GET_THREAD_TCB = 74
PT_GET_ALET = 75
PT_SWAPIN = 76
PT_EXTENDED_EVENT = 98
PT_RECOVER = 99 // Debug a program check
PT_GPR0 = 0 // General purpose register 0
PT_GPR1 = 1 // General purpose register 1
PT_GPR2 = 2 // General purpose register 2
PT_GPR3 = 3 // General purpose register 3
PT_GPR4 = 4 // General purpose register 4
PT_GPR5 = 5 // General purpose register 5
PT_GPR6 = 6 // General purpose register 6
PT_GPR7 = 7 // General purpose register 7
PT_GPR8 = 8 // General purpose register 8
PT_GPR9 = 9 // General purpose register 9
PT_GPR10 = 10 // General purpose register 10
PT_GPR11 = 11 // General purpose register 11
PT_GPR12 = 12 // General purpose register 12
PT_GPR13 = 13 // General purpose register 13
PT_GPR14 = 14 // General purpose register 14
PT_GPR15 = 15 // General purpose register 15
PT_FPR0 = 16 // Floating point register 0
PT_FPR1 = 17 // Floating point register 1
PT_FPR2 = 18 // Floating point register 2
PT_FPR3 = 19 // Floating point register 3
PT_FPR4 = 20 // Floating point register 4
PT_FPR5 = 21 // Floating point register 5
PT_FPR6 = 22 // Floating point register 6
PT_FPR7 = 23 // Floating point register 7
PT_FPR8 = 24 // Floating point register 8
PT_FPR9 = 25 // Floating point register 9
PT_FPR10 = 26 // Floating point register 10
PT_FPR11 = 27 // Floating point register 11
PT_FPR12 = 28 // Floating point register 12
PT_FPR13 = 29 // Floating point register 13
PT_FPR14 = 30 // Floating point register 14
PT_FPR15 = 31 // Floating point register 15
PT_FPC = 32 // Floating point control register
PT_PSW = 40 // PSW
PT_PSW0 = 40 // Left half of the PSW
PT_PSW1 = 41 // Right half of the PSW
PT_CR0 = 42 // Control register 0
PT_CR1 = 43 // Control register 1
PT_CR2 = 44 // Control register 2
PT_CR3 = 45 // Control register 3
PT_CR4 = 46 // Control register 4
PT_CR5 = 47 // Control register 5
PT_CR6 = 48 // Control register 6
PT_CR7 = 49 // Control register 7
PT_CR8 = 50 // Control register 8
PT_CR9 = 51 // Control register 9
PT_CR10 = 52 // Control register 10
PT_CR11 = 53 // Control register 11
PT_CR12 = 54 // Control register 12
PT_CR13 = 55 // Control register 13
PT_CR14 = 56 // Control register 14
PT_CR15 = 57 // Control register 15
PT_GPRH0 = 58 // GP High register 0
PT_GPRH1 = 59 // GP High register 1
PT_GPRH2 = 60 // GP High register 2
PT_GPRH3 = 61 // GP High register 3
PT_GPRH4 = 62 // GP High register 4
PT_GPRH5 = 63 // GP High register 5
PT_GPRH6 = 64 // GP High register 6
PT_GPRH7 = 65 // GP High register 7
PT_GPRH8 = 66 // GP High register 8
PT_GPRH9 = 67 // GP High register 9
PT_GPRH10 = 68 // GP High register 10
PT_GPRH11 = 69 // GP High register 11
PT_GPRH12 = 70 // GP High register 12
PT_GPRH13 = 71 // GP High register 13
PT_GPRH14 = 72 // GP High register 14
PT_GPRH15 = 73 // GP High register 15
PT_VR0 = 74 // Vector register 0
PT_VR1 = 75 // Vector register 1
PT_VR2 = 76 // Vector register 2
PT_VR3 = 77 // Vector register 3
PT_VR4 = 78 // Vector register 4
PT_VR5 = 79 // Vector register 5
PT_VR6 = 80 // Vector register 6
PT_VR7 = 81 // Vector register 7
PT_VR8 = 82 // Vector register 8
PT_VR9 = 83 // Vector register 9
PT_VR10 = 84 // Vector register 10
PT_VR11 = 85 // Vector register 11
PT_VR12 = 86 // Vector register 12
PT_VR13 = 87 // Vector register 13
PT_VR14 = 88 // Vector register 14
PT_VR15 = 89 // Vector register 15
PT_VR16 = 90 // Vector register 16
PT_VR17 = 91 // Vector register 17
PT_VR18 = 92 // Vector register 18
PT_VR19 = 93 // Vector register 19
PT_VR20 = 94 // Vector register 20
PT_VR21 = 95 // Vector register 21
PT_VR22 = 96 // Vector register 22
PT_VR23 = 97 // Vector register 23
PT_VR24 = 98 // Vector register 24
PT_VR25 = 99 // Vector register 25
PT_VR26 = 100 // Vector register 26
PT_VR27 = 101 // Vector register 27
PT_VR28 = 102 // Vector register 28
PT_VR29 = 103 // Vector register 29
PT_VR30 = 104 // Vector register 30
PT_VR31 = 105 // Vector register 31
PT_PSWG = 106 // PSWG
PT_PSWG0 = 106 // Bytes 0-3
PT_PSWG1 = 107 // Bytes 4-7
PT_PSWG2 = 108 // Bytes 8-11 (IA high word)
PT_PSWG3 = 109 // Bytes 12-15 (IA low word)
)
func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) {
var parms [8]unsafe.Pointer
parms[0] = unsafe.Pointer(&request)
parms[1] = unsafe.Pointer(&pid)
parms[2] = unsafe.Pointer(&addr)
parms[3] = unsafe.Pointer(&data)
parms[4] = unsafe.Pointer(&buffer)
parms[5] = unsafe.Pointer(&rv)
parms[6] = unsafe.Pointer(&rc)
parms[7] = unsafe.Pointer(&rn)
bpxcall(parms[:], BPX4PTR)
return rv, rc, rn
}
func copyU8(val uint8, dest []uint8) int {
if len(dest) < 1 {
return 0
}
dest[0] = val
return 1
}
func copyU8Arr(src, dest []uint8) int {
if len(dest) < len(src) {
return 0
}
for i, v := range src {
dest[i] = v
}
return len(src)
}
func copyU16(val uint16, dest []uint16) int {
if len(dest) < 1 {
return 0
}
dest[0] = val
return 1
}
func copyU32(val uint32, dest []uint32) int {
if len(dest) < 1 {
return 0
}
dest[0] = val
return 1
}
func copyU32Arr(src, dest []uint32) int {
if len(dest) < len(src) {
return 0
}
for i, v := range src {
dest[i] = v
}
return len(src)
}
func copyU64(val uint64, dest []uint64) int {
if len(dest) < 1 {
return 0
}
dest[0] = val
return 1
}

192
vendor/golang.org/x/sys/unix/bpxsvc_zos.s generated vendored Normal file
View File

@@ -0,0 +1,192 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go_asm.h"
#include "textflag.h"
// function to call USS assembly language services
//
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm
//
// arg1 unsafe.Pointer array that ressembles an OS PLIST
//
// arg2 function offset as in
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm
//
// func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0
MOVD plist_base+0(FP), R1 // r1 points to plist
MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table
MOVD R14, R7 // save r14
MOVD R15, R8 // save r15
MOVWZ 16(R0), R9
MOVWZ 544(R9), R9
MOVWZ 24(R9), R9 // call vector in r9
ADD R2, R9 // add offset to vector table
MOVWZ (R9), R9 // r9 points to entry point
BYTE $0x0D // BL R14,R9 --> basr r14,r9
BYTE $0xE9 // clobbers 0,1,14,15
MOVD R8, R15 // restore 15
JMP R7 // return via saved return address
// func A2e(arr [] byte)
// code page conversion from 819 to 1047
TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0
MOVD arg_base+0(FP), R2 // pointer to arry of characters
MOVD arg_len+8(FP), R3 // count
XOR R0, R0
XOR R1, R1
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
// ASCII -> EBCDIC conversion table:
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f
BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26
BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b
BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d
BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e
BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61
BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3
BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7
BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e
BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f
BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3
BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7
BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2
BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6
BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2
BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6
BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad
BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d
BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83
BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87
BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92
BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96
BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2
BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6
BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0
BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07
BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23
BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17
BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b
BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b
BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08
BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b
BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff
BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1
BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5
BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a
BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc
BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa
BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3
BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b
BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab
BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66
BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68
BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73
BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77
BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee
BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf
BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb
BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59
BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46
BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48
BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53
BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57
BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce
BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1
BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb
BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf
retry:
WORD $0xB9931022 // TROO 2,2,b'0001'
BVS retry
RET
// func e2a(arr [] byte)
// code page conversion from 1047 to 819
TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0
MOVD arg_base+0(FP), R2 // pointer to arry of characters
MOVD arg_len+8(FP), R3 // count
XOR R0, R0
XOR R1, R1
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
// EBCDIC -> ASCII conversion table:
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f
BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87
BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83
BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b
BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b
BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07
BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93
BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04
BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b
BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a
BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4
BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5
BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e
BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c
BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb
BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef
BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24
BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e
BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4
BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5
BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c
BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f
BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb
BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf
BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23
BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22
BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63
BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67
BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb
BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1
BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c
BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70
BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba
BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4
BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74
BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78
BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf
BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae
BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7
BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc
BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8
BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7
BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43
BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47
BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4
BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5
BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c
BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50
BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb
BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff
BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54
BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58
BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4
BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5
BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37
BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb
BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f
retry:
WORD $0xB9931022 // TROO 2,2,b'0001'
BVS retry
RET

View File

@@ -1,220 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build zos && s390x
package unix
import (
"sync"
)
// This file simulates epoll on z/OS using poll.
// Analogous to epoll_event on Linux.
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
type EpollEvent struct {
Events uint32
Fd int32
Pad int32
}
const (
EPOLLERR = 0x8
EPOLLHUP = 0x10
EPOLLIN = 0x1
EPOLLMSG = 0x400
EPOLLOUT = 0x4
EPOLLPRI = 0x2
EPOLLRDBAND = 0x80
EPOLLRDNORM = 0x40
EPOLLWRBAND = 0x200
EPOLLWRNORM = 0x100
EPOLL_CTL_ADD = 0x1
EPOLL_CTL_DEL = 0x2
EPOLL_CTL_MOD = 0x3
// The following constants are part of the epoll API, but represent
// currently unsupported functionality on z/OS.
// EPOLL_CLOEXEC = 0x80000
// EPOLLET = 0x80000000
// EPOLLONESHOT = 0x40000000
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
)
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
// epToPollEvt converts epoll event field to poll equivalent.
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
func epToPollEvt(events uint32) int16 {
var ep2p = map[uint32]int16{
EPOLLIN: POLLIN,
EPOLLOUT: POLLOUT,
EPOLLHUP: POLLHUP,
EPOLLPRI: POLLPRI,
EPOLLERR: POLLERR,
}
var pollEvts int16 = 0
for epEvt, pEvt := range ep2p {
if (events & epEvt) != 0 {
pollEvts |= pEvt
}
}
return pollEvts
}
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
func pToEpollEvt(revents int16) uint32 {
var p2ep = map[int16]uint32{
POLLIN: EPOLLIN,
POLLOUT: EPOLLOUT,
POLLHUP: EPOLLHUP,
POLLPRI: EPOLLPRI,
POLLERR: EPOLLERR,
}
var epollEvts uint32 = 0
for pEvt, epEvt := range p2ep {
if (revents & pEvt) != 0 {
epollEvts |= epEvt
}
}
return epollEvts
}
// Per-process epoll implementation.
type epollImpl struct {
mu sync.Mutex
epfd2ep map[int]*eventPoll
nextEpfd int
}
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
// On Linux, this is an in-kernel data structure accessed through a fd.
type eventPoll struct {
mu sync.Mutex
fds map[int]*EpollEvent
}
// epoll impl for this process.
var impl epollImpl = epollImpl{
epfd2ep: make(map[int]*eventPoll),
nextEpfd: 0,
}
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
e.mu.Lock()
defer e.mu.Unlock()
epfd = e.nextEpfd
e.nextEpfd++
e.epfd2ep[epfd] = &eventPoll{
fds: make(map[int]*EpollEvent),
}
return epfd, nil
}
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
return e.epollcreate(4)
}
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
e.mu.Lock()
defer e.mu.Unlock()
ep, ok := e.epfd2ep[epfd]
if !ok {
return EBADF
}
switch op {
case EPOLL_CTL_ADD:
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
// loops here (instances watching each other) and return ELOOP.
if _, ok := ep.fds[fd]; ok {
return EEXIST
}
ep.fds[fd] = event
case EPOLL_CTL_MOD:
if _, ok := ep.fds[fd]; !ok {
return ENOENT
}
ep.fds[fd] = event
case EPOLL_CTL_DEL:
if _, ok := ep.fds[fd]; !ok {
return ENOENT
}
delete(ep.fds, fd)
}
return nil
}
// Must be called while holding ep.mu
func (ep *eventPoll) getFds() []int {
fds := make([]int, len(ep.fds))
for fd := range ep.fds {
fds = append(fds, fd)
}
return fds
}
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
ep, ok := e.epfd2ep[epfd]
if !ok {
e.mu.Unlock()
return 0, EBADF
}
pollfds := make([]PollFd, 4)
for fd, epollevt := range ep.fds {
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
}
e.mu.Unlock()
n, err = Poll(pollfds, msec)
if err != nil {
return n, err
}
i := 0
for _, pFd := range pollfds {
if pFd.Revents != 0 {
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
i++
}
if i == n {
break
}
}
return n, nil
}
func EpollCreate(size int) (fd int, err error) {
return impl.epollcreate(size)
}
func EpollCreate1(flag int) (fd int, err error) {
return impl.epollcreate1(flag)
}
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
return impl.epollctl(epfd, op, fd, event)
}
// Because EpollWait mutates events, the caller is expected to coordinate
// concurrent access if calling with the same epfd from multiple goroutines.
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
return impl.epollwait(epfd, events, msec)
}

View File

@@ -1,163 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build zos && s390x
package unix
import (
"unsafe"
)
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
func Fstatfs(fd int, stat *Statfs_t) (err error) {
var stat_v Statvfs_t
err = Fstatvfs(fd, &stat_v)
if err == nil {
// populate stat
stat.Type = 0
stat.Bsize = stat_v.Bsize
stat.Blocks = stat_v.Blocks
stat.Bfree = stat_v.Bfree
stat.Bavail = stat_v.Bavail
stat.Files = stat_v.Files
stat.Ffree = stat_v.Ffree
stat.Fsid = stat_v.Fsid
stat.Namelen = stat_v.Namemax
stat.Frsize = stat_v.Frsize
stat.Flags = stat_v.Flag
for passn := 0; passn < 5; passn++ {
switch passn {
case 0:
err = tryGetmntent64(stat)
break
case 1:
err = tryGetmntent128(stat)
break
case 2:
err = tryGetmntent256(stat)
break
case 3:
err = tryGetmntent512(stat)
break
case 4:
err = tryGetmntent1024(stat)
break
default:
break
}
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
if err == nil || err != nil && err != ERANGE {
break
}
}
}
return err
}
func tryGetmntent64(stat *Statfs_t) (err error) {
var mnt_ent_buffer struct {
header W_Mnth
filesys_info [64]W_Mntent
}
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
if err != nil {
return err
}
err = ERANGE //return ERANGE if no match is found in this batch
for i := 0; i < fs_count; i++ {
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
err = nil
break
}
}
return err
}
func tryGetmntent128(stat *Statfs_t) (err error) {
var mnt_ent_buffer struct {
header W_Mnth
filesys_info [128]W_Mntent
}
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
if err != nil {
return err
}
err = ERANGE //return ERANGE if no match is found in this batch
for i := 0; i < fs_count; i++ {
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
err = nil
break
}
}
return err
}
func tryGetmntent256(stat *Statfs_t) (err error) {
var mnt_ent_buffer struct {
header W_Mnth
filesys_info [256]W_Mntent
}
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
if err != nil {
return err
}
err = ERANGE //return ERANGE if no match is found in this batch
for i := 0; i < fs_count; i++ {
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
err = nil
break
}
}
return err
}
func tryGetmntent512(stat *Statfs_t) (err error) {
var mnt_ent_buffer struct {
header W_Mnth
filesys_info [512]W_Mntent
}
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
if err != nil {
return err
}
err = ERANGE //return ERANGE if no match is found in this batch
for i := 0; i < fs_count; i++ {
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
err = nil
break
}
}
return err
}
func tryGetmntent1024(stat *Statfs_t) (err error) {
var mnt_ent_buffer struct {
header W_Mnth
filesys_info [1024]W_Mntent
}
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
if err != nil {
return err
}
err = ERANGE //return ERANGE if no match is found in this batch
for i := 0; i < fs_count; i++ {
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
err = nil
break
}
}
return err
}

View File

@@ -58,6 +58,7 @@ includes_Darwin='
#define _DARWIN_USE_64_BIT_INODE
#define __APPLE_USE_RFC_3542
#include <stdint.h>
#include <sys/stdio.h>
#include <sys/attr.h>
#include <sys/clonefile.h>
#include <sys/kern_control.h>
@@ -263,6 +264,7 @@ struct ltchars {
#include <linux/sched.h>
#include <linux/seccomp.h>
#include <linux/serial.h>
#include <linux/sock_diag.h>
#include <linux/sockios.h>
#include <linux/taskstats.h>
#include <linux/tipc.h>
@@ -549,6 +551,8 @@ ccflags="$@"
$2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ ||
$2 ~ /^(CONNECT|SAE)_/ ||
$2 ~ /^FIORDCHK$/ ||
$2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ ||
@@ -584,7 +588,7 @@ ccflags="$@"
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
$2 ~ /^KEYCTL_/ ||
$2 ~ /^PERF_/ ||
$2 ~ /^SECCOMP_MODE_/ ||
$2 ~ /^SECCOMP_/ ||
$2 ~ /^SEEK_/ ||
$2 ~ /^SCHED_/ ||
$2 ~ /^SPLICE_/ ||

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
package unix

View File

@@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
return mapper.Mremap(oldData, newLength, flags)
}
func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) {
xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr))
return unsafe.Pointer(xaddr), err
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// For Unix, get the pagesize from the runtime.

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin
//go:build darwin || zos
package unix

58
vendor/golang.org/x/sys/unix/sockcmsg_zos.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Socket control messages
package unix
import "unsafe"
// UnixCredentials encodes credentials into a socket control message
// for sending to another process. This can be used for
// authentication.
func UnixCredentials(ucred *Ucred) []byte {
b := make([]byte, CmsgSpace(SizeofUcred))
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = SOL_SOCKET
h.Type = SCM_CREDENTIALS
h.SetLen(CmsgLen(SizeofUcred))
*(*Ucred)(h.data(0)) = *ucred
return b
}
// ParseUnixCredentials decodes a socket control message that contains
// credentials in a Ucred structure. To receive such a message, the
// SO_PASSCRED option must be enabled on the socket.
func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
if m.Header.Level != SOL_SOCKET {
return nil, EINVAL
}
if m.Header.Type != SCM_CREDENTIALS {
return nil, EINVAL
}
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
return &ucred, nil
}
// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
func PktInfo4(info *Inet4Pktinfo) []byte {
b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = SOL_IP
h.Type = IP_PKTINFO
h.SetLen(CmsgLen(SizeofInet4Pktinfo))
*(*Inet4Pktinfo)(h.data(0)) = *info
return b
}
// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
func PktInfo6(info *Inet6Pktinfo) []byte {
b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = SOL_IPV6
h.Type = IPV6_PKTINFO
h.SetLen(CmsgLen(SizeofInet6Pktinfo))
*(*Inet6Pktinfo)(h.data(0)) = *info
return b
}

75
vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s generated vendored Normal file
View File

@@ -0,0 +1,75 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build zos && s390x && gc
#include "textflag.h"
// provide the address of function variable to be fixed up.
TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Pipe2(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Flock(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Getxattr(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Nanosleep(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Setxattr(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Wait4(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Mount(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Unmount(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·UtimesNanoAt(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·UtimesNano(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Mkfifoat(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Chtag(SB), R8
MOVD R8, ret+0(FP)
RET
TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Readlinkat(SB), R8
MOVD R8, ret+0(FP)
RET

View File

@@ -402,6 +402,18 @@ func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error {
return ioctlPtr(fd, SIOCSIFMTU, unsafe.Pointer(ifreq))
}
//sys renamexNp(from string, to string, flag uint32) (err error)
func RenamexNp(from string, to string, flag uint32) (err error) {
return renamexNp(from, to, flag)
}
//sys renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error)
func RenameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) {
return renameatxNp(fromfd, from, tofd, to, flag)
}
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL
func Uname(uname *Utsname) error {
@@ -542,6 +554,55 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
}
}
//sys pthread_chdir_np(path string) (err error)
func PthreadChdir(path string) (err error) {
return pthread_chdir_np(path)
}
//sys pthread_fchdir_np(fd int) (err error)
func PthreadFchdir(fd int) (err error) {
return pthread_fchdir_np(fd)
}
// Connectx calls connectx(2) to initiate a connection on a socket.
//
// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument.
//
// - srcIf is the optional source interface index. 0 means unspecified.
// - srcAddr is the optional source address. nil means unspecified.
// - dstAddr is the destination address.
//
// On success, Connectx returns the number of bytes enqueued for transmission.
func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) {
endpoints := SaEndpoints{
Srcif: srcIf,
}
if srcAddr != nil {
addrp, addrlen, err := srcAddr.sockaddr()
if err != nil {
return 0, err
}
endpoints.Srcaddr = (*RawSockaddr)(addrp)
endpoints.Srcaddrlen = uint32(addrlen)
}
if dstAddr != nil {
addrp, addrlen, err := dstAddr.sockaddr()
if err != nil {
return 0, err
}
endpoints.Dstaddr = (*RawSockaddr)(addrp)
endpoints.Dstaddrlen = uint32(addrlen)
}
err = connectx(fd, &endpoints, associd, flags, iov, &n, connid)
return
}
//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error)
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin && go1.12
//go:build darwin
package unix

View File

@@ -13,6 +13,7 @@
package unix
import (
"errors"
"sync"
"unsafe"
)
@@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
n := unsafe.Sizeof(uname.Sysname)
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
// Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
n = unsafe.Sizeof(uname.Nodename)
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
n = unsafe.Sizeof(uname.Release)
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_VERSION}
n = unsafe.Sizeof(uname.Version)
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
@@ -205,7 +207,7 @@ func Uname(uname *Utsname) error {
mib = []_C_int{CTL_HW, HW_MACHINE}
n = unsafe.Sizeof(uname.Machine)
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}

View File

@@ -11,6 +11,7 @@ package unix
int ioctl(int, unsigned long int, uintptr_t);
*/
import "C"
import "unsafe"
func ioctl(fd int, req uint, arg uintptr) (err error) {
r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg))

View File

@@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error {
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
//sys Fsopen(fsName string, flags int) (fd int, err error)
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error)
func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) {
var keyp *byte
if keyp, err = BytePtrFromString(key); err != nil {
return
}
return fsconfig(fd, cmd, keyp, value, aux)
}
// FsconfigSetFlag is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FLAG.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
func FsconfigSetFlag(fd int, key string) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0)
}
// FsconfigSetString is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_STRING.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetString(fd int, key string, value string) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(value); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0)
}
// FsconfigSetBinary is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_BINARY.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetBinary(fd int, key string, value []byte) (err error) {
if len(value) == 0 {
return EINVAL
}
return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value))
}
// FsconfigSetPath is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// path is a non-empty path for specified key.
// atfd is a file descriptor at which to start lookup from or AT_FDCWD.
func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd)
}
// FsconfigSetPathEmpty is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as
// FconfigSetPath but with AT_PATH_EMPTY implied.
func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd)
}
// FsconfigSetFd is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FD.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is a file descriptor to be assigned to specified key.
func FsconfigSetFd(fd int, key string, value int) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value)
}
// FsconfigCreate is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_CREATE.
//
// fd is the filesystem context to act upon.
func FsconfigCreate(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0)
}
// FsconfigReconfigure is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_RECONFIGURE.
//
// fd is the filesystem context to act upon.
func FsconfigReconfigure(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
}
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb Getpgid(pid int) (pgid int, err error)
@@ -2493,3 +2592,4 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
}
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
//sys Mseal(b []byte, flags uint) (err error)

View File

@@ -293,6 +293,7 @@ func Uname(uname *Utsname) error {
//sys Mkfifoat(dirfd int, path string, mode uint32) (err error)
//sys Mknod(path string, mode uint32, dev int) (err error)
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error)
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error)

View File

@@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) {
xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset)
return unsafe.Pointer(xaddr), err
}
func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) {
return mapper.munmap(uintptr(addr), length)
}
func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p)
if raceenabled {

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (darwin && !ios) || linux
//go:build (darwin && !ios) || linux || zos
package unix

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin && !ios
//go:build (darwin && !ios) || zos
package unix

View File

@@ -237,6 +237,9 @@ const (
CLOCK_UPTIME_RAW_APPROX = 0x9
CLONE_NOFOLLOW = 0x1
CLONE_NOOWNERCOPY = 0x2
CONNECT_DATA_AUTHENTICATED = 0x4
CONNECT_DATA_IDEMPOTENT = 0x2
CONNECT_RESUME_ON_READ_WRITE = 0x1
CR0 = 0x0
CR1 = 0x1000
CR2 = 0x2000
@@ -1169,6 +1172,11 @@ const (
PT_WRITE_D = 0x5
PT_WRITE_I = 0x4
PT_WRITE_U = 0x6
RENAME_EXCL = 0x4
RENAME_NOFOLLOW_ANY = 0x10
RENAME_RESERVED1 = 0x8
RENAME_SECLUDE = 0x1
RENAME_SWAP = 0x2
RLIMIT_AS = 0x5
RLIMIT_CORE = 0x4
RLIMIT_CPU = 0x0
@@ -1260,6 +1268,10 @@ const (
RTV_SSTHRESH = 0x20
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
SAE_ASSOCID_ALL = 0xffffffff
SAE_ASSOCID_ANY = 0x0
SAE_CONNID_ALL = 0xffffffff
SAE_CONNID_ANY = 0x0
SCM_CREDS = 0x3
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x2

View File

@@ -237,6 +237,9 @@ const (
CLOCK_UPTIME_RAW_APPROX = 0x9
CLONE_NOFOLLOW = 0x1
CLONE_NOOWNERCOPY = 0x2
CONNECT_DATA_AUTHENTICATED = 0x4
CONNECT_DATA_IDEMPOTENT = 0x2
CONNECT_RESUME_ON_READ_WRITE = 0x1
CR0 = 0x0
CR1 = 0x1000
CR2 = 0x2000
@@ -1169,6 +1172,11 @@ const (
PT_WRITE_D = 0x5
PT_WRITE_I = 0x4
PT_WRITE_U = 0x6
RENAME_EXCL = 0x4
RENAME_NOFOLLOW_ANY = 0x10
RENAME_RESERVED1 = 0x8
RENAME_SECLUDE = 0x1
RENAME_SWAP = 0x2
RLIMIT_AS = 0x5
RLIMIT_CORE = 0x4
RLIMIT_CPU = 0x0
@@ -1260,6 +1268,10 @@ const (
RTV_SSTHRESH = 0x20
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
SAE_ASSOCID_ALL = 0xffffffff
SAE_ASSOCID_ANY = 0x0
SAE_CONNID_ALL = 0xffffffff
SAE_CONNID_ANY = 0x0
SCM_CREDS = 0x3
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x2

View File

@@ -457,6 +457,7 @@ const (
B600 = 0x8
B75 = 0x2
B9600 = 0xd
BCACHEFS_SUPER_MAGIC = 0xca451a4e
BDEVFS_MAGIC = 0x62646576
BINDERFS_SUPER_MAGIC = 0x6c6f6f70
BINFMTFS_MAGIC = 0x42494e4d
@@ -491,6 +492,7 @@ const (
BPF_F_REPLACE = 0x4
BPF_F_SLEEPABLE = 0x10
BPF_F_STRICT_ALIGNMENT = 0x1
BPF_F_TEST_REG_INVARIANTS = 0x80
BPF_F_TEST_RND_HI32 = 0x4
BPF_F_TEST_RUN_ON_CPU = 0x1
BPF_F_TEST_STATE_FREQ = 0x8
@@ -501,6 +503,7 @@ const (
BPF_IMM = 0x0
BPF_IND = 0x40
BPF_JA = 0x0
BPF_JCOND = 0xe0
BPF_JEQ = 0x10
BPF_JGE = 0x30
BPF_JGT = 0x20
@@ -656,6 +659,9 @@ const (
CAN_NPROTO = 0x8
CAN_RAW = 0x1
CAN_RAW_FILTER_MAX = 0x200
CAN_RAW_XL_VCID_RX_FILTER = 0x4
CAN_RAW_XL_VCID_TX_PASS = 0x2
CAN_RAW_XL_VCID_TX_SET = 0x1
CAN_RTR_FLAG = 0x40000000
CAN_SFF_ID_BITS = 0xb
CAN_SFF_MASK = 0x7ff
@@ -923,6 +929,7 @@ const (
EPOLL_CTL_ADD = 0x1
EPOLL_CTL_DEL = 0x2
EPOLL_CTL_MOD = 0x3
EPOLL_IOC_TYPE = 0x8a
EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2
ESP_V4_FLOW = 0xa
ESP_V6_FLOW = 0xc
@@ -936,9 +943,6 @@ const (
ETHTOOL_FEC_OFF = 0x4
ETHTOOL_FEC_RS = 0x8
ETHTOOL_FLAG_ALL = 0x7
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
ETHTOOL_FLAG_OMIT_REPLY = 0x2
ETHTOOL_FLAG_STATS = 0x4
ETHTOOL_FLASHDEV = 0x33
ETHTOOL_FLASH_MAX_FILENAME = 0x80
ETHTOOL_FWVERS_LEN = 0x20
@@ -1338,6 +1342,7 @@ const (
F_OFD_SETLK = 0x25
F_OFD_SETLKW = 0x26
F_OK = 0x0
F_SEAL_EXEC = 0x20
F_SEAL_FUTURE_WRITE = 0x10
F_SEAL_GROW = 0x4
F_SEAL_SEAL = 0x1
@@ -1626,6 +1631,7 @@ const (
IP_FREEBIND = 0xf
IP_HDRINCL = 0x3
IP_IPSEC_POLICY = 0x10
IP_LOCAL_PORT_RANGE = 0x33
IP_MAXPACKET = 0xffff
IP_MAX_MEMBERSHIPS = 0x14
IP_MF = 0x2000
@@ -1652,6 +1658,7 @@ const (
IP_PMTUDISC_OMIT = 0x5
IP_PMTUDISC_PROBE = 0x3
IP_PMTUDISC_WANT = 0x1
IP_PROTOCOL = 0x34
IP_RECVERR = 0xb
IP_RECVERR_RFC4884 = 0x1a
IP_RECVFRAGSIZE = 0x19
@@ -1697,6 +1704,8 @@ const (
KEXEC_ARCH_S390 = 0x160000
KEXEC_ARCH_SH = 0x2a0000
KEXEC_ARCH_X86_64 = 0x3e0000
KEXEC_CRASH_HOTPLUG_SUPPORT = 0x8
KEXEC_FILE_DEBUG = 0x8
KEXEC_FILE_NO_INITRAMFS = 0x4
KEXEC_FILE_ON_CRASH = 0x2
KEXEC_FILE_UNLOAD = 0x1
@@ -1771,6 +1780,7 @@ const (
KEY_SPEC_USER_KEYRING = -0x4
KEY_SPEC_USER_SESSION_KEYRING = -0x5
LANDLOCK_ACCESS_FS_EXECUTE = 0x1
LANDLOCK_ACCESS_FS_IOCTL_DEV = 0x8000
LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800
LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40
LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80
@@ -1785,6 +1795,8 @@ const (
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
LANDLOCK_CREATE_RULESET_VERSION = 0x1
LINUX_REBOOT_CMD_CAD_OFF = 0x0
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
@@ -1850,6 +1862,19 @@ const (
MAP_FILE = 0x0
MAP_FIXED = 0x10
MAP_FIXED_NOREPLACE = 0x100000
MAP_HUGE_16GB = 0x88000000
MAP_HUGE_16KB = 0x38000000
MAP_HUGE_16MB = 0x60000000
MAP_HUGE_1GB = 0x78000000
MAP_HUGE_1MB = 0x50000000
MAP_HUGE_256MB = 0x70000000
MAP_HUGE_2GB = 0x7c000000
MAP_HUGE_2MB = 0x54000000
MAP_HUGE_32MB = 0x64000000
MAP_HUGE_512KB = 0x4c000000
MAP_HUGE_512MB = 0x74000000
MAP_HUGE_64KB = 0x40000000
MAP_HUGE_8MB = 0x5c000000
MAP_HUGE_MASK = 0x3f
MAP_HUGE_SHIFT = 0x1a
MAP_PRIVATE = 0x2
@@ -1896,6 +1921,7 @@ const (
MNT_DETACH = 0x2
MNT_EXPIRE = 0x4
MNT_FORCE = 0x1
MNT_ID_REQ_SIZE_VER0 = 0x18
MODULE_INIT_COMPRESSED_FILE = 0x4
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
MODULE_INIT_IGNORE_VERMAGIC = 0x2
@@ -2164,7 +2190,7 @@ const (
NFT_SECMARK_CTX_MAXLEN = 0x100
NFT_SET_MAXNAMELEN = 0x100
NFT_SOCKET_MAX = 0x3
NFT_TABLE_F_MASK = 0x3
NFT_TABLE_F_MASK = 0x7
NFT_TABLE_MAXNAMELEN = 0x100
NFT_TRACETYPE_MAX = 0x3
NFT_TUNNEL_F_MASK = 0x7
@@ -2300,6 +2326,7 @@ const (
PERF_AUX_FLAG_PARTIAL = 0x4
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
PERF_AUX_FLAG_TRUNCATED = 0x1
PERF_BRANCH_ENTRY_INFO_BITS_MAX = 0x21
PERF_BR_ARM64_DEBUG_DATA = 0x7
PERF_BR_ARM64_DEBUG_EXIT = 0x5
PERF_BR_ARM64_DEBUG_HALT = 0x4
@@ -2397,6 +2424,7 @@ const (
PERF_RECORD_MISC_USER = 0x2
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
PID_FS_MAGIC = 0x50494446
PIPEFS_MAGIC = 0x50495045
PPPIOCGNPMODE = 0xc008744c
PPPIOCNEWUNIT = 0xc004743e
@@ -2465,6 +2493,7 @@ const (
PR_MCE_KILL_GET = 0x22
PR_MCE_KILL_LATE = 0x0
PR_MCE_KILL_SET = 0x1
PR_MDWE_NO_INHERIT = 0x2
PR_MDWE_REFUSE_EXEC_GAIN = 0x1
PR_MPX_DISABLE_MANAGEMENT = 0x2c
PR_MPX_ENABLE_MANAGEMENT = 0x2b
@@ -2483,6 +2512,23 @@ const (
PR_PAC_GET_ENABLED_KEYS = 0x3d
PR_PAC_RESET_KEYS = 0x36
PR_PAC_SET_ENABLED_KEYS = 0x3c
PR_PPC_DEXCR_CTRL_CLEAR = 0x4
PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10
PR_PPC_DEXCR_CTRL_EDITABLE = 0x1
PR_PPC_DEXCR_CTRL_MASK = 0x1f
PR_PPC_DEXCR_CTRL_SET = 0x2
PR_PPC_DEXCR_CTRL_SET_ONEXEC = 0x8
PR_PPC_DEXCR_IBRTPD = 0x1
PR_PPC_DEXCR_NPHIE = 0x3
PR_PPC_DEXCR_SBHE = 0x0
PR_PPC_DEXCR_SRAPD = 0x2
PR_PPC_GET_DEXCR = 0x48
PR_PPC_SET_DEXCR = 0x49
PR_RISCV_CTX_SW_FENCEI_OFF = 0x1
PR_RISCV_CTX_SW_FENCEI_ON = 0x0
PR_RISCV_SCOPE_PER_PROCESS = 0x0
PR_RISCV_SCOPE_PER_THREAD = 0x1
PR_RISCV_SET_ICACHE_FLUSH_CTX = 0x47
PR_RISCV_V_GET_CONTROL = 0x46
PR_RISCV_V_SET_CONTROL = 0x45
PR_RISCV_V_VSTATE_CTRL_CUR_MASK = 0x3
@@ -2669,8 +2715,9 @@ const (
RTAX_FEATURES = 0xc
RTAX_FEATURE_ALLFRAG = 0x8
RTAX_FEATURE_ECN = 0x1
RTAX_FEATURE_MASK = 0xf
RTAX_FEATURE_MASK = 0x1f
RTAX_FEATURE_SACK = 0x2
RTAX_FEATURE_TCP_USEC_TS = 0x10
RTAX_FEATURE_TIMESTAMP = 0x4
RTAX_HOPLIMIT = 0xa
RTAX_INITCWND = 0xb
@@ -2888,8 +2935,9 @@ const (
RWF_APPEND = 0x10
RWF_DSYNC = 0x2
RWF_HIPRI = 0x1
RWF_NOAPPEND = 0x20
RWF_NOWAIT = 0x8
RWF_SUPPORTED = 0x1f
RWF_SUPPORTED = 0x3f
RWF_SYNC = 0x4
RWF_WRITE_LIFE_NOT_SET = 0x0
SCHED_BATCH = 0x3
@@ -2910,12 +2958,43 @@ const (
SCHED_RESET_ON_FORK = 0x40000000
SCHED_RR = 0x2
SCM_CREDENTIALS = 0x2
SCM_PIDFD = 0x4
SCM_RIGHTS = 0x1
SCM_SECURITY = 0x3
SCM_TIMESTAMP = 0x1d
SC_LOG_FLUSH = 0x100000
SECCOMP_ADDFD_FLAG_SEND = 0x2
SECCOMP_ADDFD_FLAG_SETFD = 0x1
SECCOMP_FILTER_FLAG_LOG = 0x2
SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8
SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4
SECCOMP_FILTER_FLAG_TSYNC = 0x1
SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10
SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20
SECCOMP_GET_ACTION_AVAIL = 0x2
SECCOMP_GET_NOTIF_SIZES = 0x3
SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100
SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101
SECCOMP_IOC_MAGIC = '!'
SECCOMP_MODE_DISABLED = 0x0
SECCOMP_MODE_FILTER = 0x2
SECCOMP_MODE_STRICT = 0x1
SECCOMP_RET_ACTION = 0x7fff0000
SECCOMP_RET_ACTION_FULL = 0xffff0000
SECCOMP_RET_ALLOW = 0x7fff0000
SECCOMP_RET_DATA = 0xffff
SECCOMP_RET_ERRNO = 0x50000
SECCOMP_RET_KILL = 0x0
SECCOMP_RET_KILL_PROCESS = 0x80000000
SECCOMP_RET_KILL_THREAD = 0x0
SECCOMP_RET_LOG = 0x7ffc0000
SECCOMP_RET_TRACE = 0x7ff00000
SECCOMP_RET_TRAP = 0x30000
SECCOMP_RET_USER_NOTIF = 0x7fc00000
SECCOMP_SET_MODE_FILTER = 0x1
SECCOMP_SET_MODE_STRICT = 0x0
SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1
SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1
SECRETMEM_MAGIC = 0x5345434d
SECURITYFS_MAGIC = 0x73636673
SEEK_CUR = 0x1
@@ -3014,6 +3093,8 @@ const (
SIOCSMIIREG = 0x8949
SIOCSRARP = 0x8962
SIOCWANDEV = 0x894a
SK_DIAG_BPF_STORAGE_MAX = 0x3
SK_DIAG_BPF_STORAGE_REQ_MAX = 0x1
SMACK_MAGIC = 0x43415d53
SMART_AUTOSAVE = 0xd2
SMART_AUTO_OFFLINE = 0xdb
@@ -3034,6 +3115,8 @@ const (
SOCKFS_MAGIC = 0x534f434b
SOCK_BUF_LOCK_MASK = 0x3
SOCK_DCCP = 0x6
SOCK_DESTROY = 0x15
SOCK_DIAG_BY_FAMILY = 0x14
SOCK_IOC_TYPE = 0x89
SOCK_PACKET = 0xa
SOCK_RAW = 0x3
@@ -3075,6 +3158,7 @@ const (
SOL_TIPC = 0x10f
SOL_TLS = 0x11a
SOL_UDP = 0x11
SOL_VSOCK = 0x11f
SOL_X25 = 0x106
SOL_XDP = 0x11b
SOMAXCONN = 0x1000
@@ -3134,10 +3218,12 @@ const (
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MNT_ID = 0x1000
STATX_MNT_ID_UNIQUE = 0x4000
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_SUBVOL = 0x8000
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
@@ -3221,6 +3307,7 @@ const (
TCP_MAX_WINSHIFT = 0xe
TCP_MD5SIG = 0xe
TCP_MD5SIG_EXT = 0x20
TCP_MD5SIG_FLAG_IFINDEX = 0x2
TCP_MD5SIG_FLAG_PREFIX = 0x1
TCP_MD5SIG_MAXKEYLEN = 0x50
TCP_MSS = 0x200
@@ -3528,12 +3615,16 @@ const (
XDP_RX_RING = 0x2
XDP_SHARED_UMEM = 0x1
XDP_STATISTICS = 0x7
XDP_TXMD_FLAGS_CHECKSUM = 0x2
XDP_TXMD_FLAGS_TIMESTAMP = 0x1
XDP_TX_METADATA = 0x2
XDP_TX_RING = 0x3
XDP_UMEM_COMPLETION_RING = 0x6
XDP_UMEM_FILL_RING = 0x5
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
XDP_UMEM_REG = 0x4
XDP_UMEM_TX_SW_CSUM = 0x2
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
XDP_USE_NEED_WAKEUP = 0x8
XDP_USE_SG = 0x10

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -118,6 +120,7 @@ const (
IXOFF = 0x1000
IXON = 0x400
MAP_32BIT = 0x40
MAP_ABOVE4G = 0x80
MAP_ANON = 0x20
MAP_ANONYMOUS = 0x20
MAP_DENYWRITE = 0x800
@@ -281,6 +284,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -118,6 +120,7 @@ const (
IXOFF = 0x1000
IXON = 0x400
MAP_32BIT = 0x40
MAP_ABOVE4G = 0x80
MAP_ANON = 0x20
MAP_ANONYMOUS = 0x20
MAP_DENYWRITE = 0x800
@@ -282,6 +285,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -288,6 +290,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
ESR_MAGIC = 0x45535201
EXTPROC = 0x10000
@@ -87,6 +89,7 @@ const (
FICLONE = 0x40049409
FICLONERANGE = 0x4020940d
FLUSHO = 0x1000
FPMR_MAGIC = 0x46504d52
FPSIMD_MAGIC = 0x46508001
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80086601
@@ -278,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -275,6 +277,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x80
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -281,6 +283,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x80
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -281,6 +283,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x80
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -281,6 +283,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x80
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -281,6 +283,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x20
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000000
FF1 = 0x4000
@@ -336,6 +338,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x20
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000000
FF1 = 0x4000
@@ -340,6 +342,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x20
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000000
FF1 = 0x4000
@@ -340,6 +342,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -272,6 +274,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -78,6 +78,8 @@ const (
ECHOPRT = 0x400
EFD_CLOEXEC = 0x80000
EFD_NONBLOCK = 0x800
EPIOCGPARAMS = 0x80088a02
EPIOCSPARAMS = 0x40088a01
EPOLL_CLOEXEC = 0x80000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -344,6 +346,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

View File

@@ -82,6 +82,8 @@ const (
EFD_CLOEXEC = 0x400000
EFD_NONBLOCK = 0x4000
EMT_TAGOVF = 0x1
EPIOCGPARAMS = 0x40088a02
EPIOCSPARAMS = 0x80088a01
EPOLL_CLOEXEC = 0x400000
EXTPROC = 0x10000
FF1 = 0x8000
@@ -335,6 +337,9 @@ const (
SCM_TIMESTAMPNS = 0x21
SCM_TXTIME = 0x3f
SCM_WIFI_STATUS = 0x25
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x400000
SFD_NONBLOCK = 0x4000
SF_FP = 0x38

View File

@@ -10,41 +10,99 @@
package unix
const (
BRKINT = 0x0001
CLOCK_MONOTONIC = 0x1
CLOCK_PROCESS_CPUTIME_ID = 0x2
CLOCK_REALTIME = 0x0
CLOCK_THREAD_CPUTIME_ID = 0x3
CS8 = 0x0030
CSIZE = 0x0030
ECHO = 0x00000008
ECHONL = 0x00000001
FD_CLOEXEC = 0x01
FD_CLOFORK = 0x02
FNDELAY = 0x04
F_CLOSFD = 9
F_CONTROL_CVT = 13
F_DUPFD = 0
F_DUPFD2 = 8
F_GETFD = 1
F_GETFL = 259
F_GETLK = 5
F_GETOWN = 10
F_OK = 0x0
F_RDLCK = 1
F_SETFD = 2
F_SETFL = 4
F_SETLK = 6
F_SETLKW = 7
F_SETOWN = 11
F_SETTAG = 12
F_UNLCK = 3
F_WRLCK = 2
FSTYPE_ZFS = 0xe9 //"Z"
FSTYPE_HFS = 0xc8 //"H"
FSTYPE_NFS = 0xd5 //"N"
FSTYPE_TFS = 0xe3 //"T"
FSTYPE_AUTOMOUNT = 0xc1 //"A"
BRKINT = 0x0001
CLOCAL = 0x1
CLOCK_MONOTONIC = 0x1
CLOCK_PROCESS_CPUTIME_ID = 0x2
CLOCK_REALTIME = 0x0
CLOCK_THREAD_CPUTIME_ID = 0x3
CLONE_NEWIPC = 0x08000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x00020000
CLONE_NEWPID = 0x20000000
CLONE_NEWUTS = 0x04000000
CLONE_PARENT = 0x00008000
CS8 = 0x0030
CSIZE = 0x0030
ECHO = 0x00000008
ECHONL = 0x00000001
EFD_SEMAPHORE = 0x00002000
EFD_CLOEXEC = 0x00001000
EFD_NONBLOCK = 0x00000004
EPOLL_CLOEXEC = 0x00001000
EPOLL_CTL_ADD = 0
EPOLL_CTL_MOD = 1
EPOLL_CTL_DEL = 2
EPOLLRDNORM = 0x0001
EPOLLRDBAND = 0x0002
EPOLLIN = 0x0003
EPOLLOUT = 0x0004
EPOLLWRBAND = 0x0008
EPOLLPRI = 0x0010
EPOLLERR = 0x0020
EPOLLHUP = 0x0040
EPOLLEXCLUSIVE = 0x20000000
EPOLLONESHOT = 0x40000000
FD_CLOEXEC = 0x01
FD_CLOFORK = 0x02
FD_SETSIZE = 0x800
FNDELAY = 0x04
F_CLOSFD = 9
F_CONTROL_CVT = 13
F_DUPFD = 0
F_DUPFD2 = 8
F_GETFD = 1
F_GETFL = 259
F_GETLK = 5
F_GETOWN = 10
F_OK = 0x0
F_RDLCK = 1
F_SETFD = 2
F_SETFL = 4
F_SETLK = 6
F_SETLKW = 7
F_SETOWN = 11
F_SETTAG = 12
F_UNLCK = 3
F_WRLCK = 2
FSTYPE_ZFS = 0xe9 //"Z"
FSTYPE_HFS = 0xc8 //"H"
FSTYPE_NFS = 0xd5 //"N"
FSTYPE_TFS = 0xe3 //"T"
FSTYPE_AUTOMOUNT = 0xc1 //"A"
GRND_NONBLOCK = 1
GRND_RANDOM = 2
HUPCL = 0x0100 // Hang up on last close
IN_CLOEXEC = 0x00001000
IN_NONBLOCK = 0x00000004
IN_ACCESS = 0x00000001
IN_MODIFY = 0x00000002
IN_ATTRIB = 0x00000004
IN_CLOSE_WRITE = 0x00000008
IN_CLOSE_NOWRITE = 0x00000010
IN_OPEN = 0x00000020
IN_MOVED_FROM = 0x00000040
IN_MOVED_TO = 0x00000080
IN_CREATE = 0x00000100
IN_DELETE = 0x00000200
IN_DELETE_SELF = 0x00000400
IN_MOVE_SELF = 0x00000800
IN_UNMOUNT = 0x00002000
IN_Q_OVERFLOW = 0x00004000
IN_IGNORED = 0x00008000
IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO)
IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB |
IN_CLOSE | IN_OPEN | IN_MOVE |
IN_CREATE | IN_DELETE | IN_DELETE_SELF |
IN_MOVE_SELF)
IN_ONLYDIR = 0x01000000
IN_DONT_FOLLOW = 0x02000000
IN_EXCL_UNLINK = 0x04000000
IN_MASK_CREATE = 0x10000000
IN_MASK_ADD = 0x20000000
IN_ISDIR = 0x40000000
IN_ONESHOT = 0x80000000
IP6F_MORE_FRAG = 0x0001
IP6F_OFF_MASK = 0xfff8
IP6F_RESERVED_MASK = 0x0006
@@ -152,10 +210,18 @@ const (
IP_PKTINFO = 101
IP_RECVPKTINFO = 102
IP_TOS = 2
IP_TTL = 3
IP_TTL = 14
IP_UNBLOCK_SOURCE = 11
ICMP6_FILTER = 1
MCAST_INCLUDE = 0
MCAST_EXCLUDE = 1
MCAST_JOIN_GROUP = 40
MCAST_LEAVE_GROUP = 41
MCAST_JOIN_SOURCE_GROUP = 42
MCAST_LEAVE_SOURCE_GROUP = 43
MCAST_BLOCK_SOURCE = 44
MCAST_UNBLOCK_SOURCE = 46
ICANON = 0x0010
ICMP6_FILTER = 0x26
ICRNL = 0x0002
IEXTEN = 0x0020
IGNBRK = 0x0004
@@ -165,10 +231,10 @@ const (
ISTRIP = 0x0080
IXON = 0x0200
IXOFF = 0x0100
LOCK_SH = 0x1 // Not exist on zOS
LOCK_EX = 0x2 // Not exist on zOS
LOCK_NB = 0x4 // Not exist on zOS
LOCK_UN = 0x8 // Not exist on zOS
LOCK_SH = 0x1
LOCK_EX = 0x2
LOCK_NB = 0x4
LOCK_UN = 0x8
POLLIN = 0x0003
POLLOUT = 0x0004
POLLPRI = 0x0010
@@ -182,15 +248,29 @@ const (
MAP_PRIVATE = 0x1 // changes are private
MAP_SHARED = 0x2 // changes are shared
MAP_FIXED = 0x4 // place exactly
MCAST_JOIN_GROUP = 40
MCAST_LEAVE_GROUP = 41
MCAST_JOIN_SOURCE_GROUP = 42
MCAST_LEAVE_SOURCE_GROUP = 43
MCAST_BLOCK_SOURCE = 44
MCAST_UNBLOCK_SOURCE = 45
__MAP_MEGA = 0x8
__MAP_64 = 0x10
MAP_ANON = 0x20
MAP_ANONYMOUS = 0x20
MS_SYNC = 0x1 // msync - synchronous writes
MS_ASYNC = 0x2 // asynchronous writes
MS_INVALIDATE = 0x4 // invalidate mappings
MS_BIND = 0x00001000
MS_MOVE = 0x00002000
MS_NOSUID = 0x00000002
MS_PRIVATE = 0x00040000
MS_REC = 0x00004000
MS_REMOUNT = 0x00008000
MS_RDONLY = 0x00000001
MS_UNBINDABLE = 0x00020000
MNT_DETACH = 0x00000004
ZOSDSFS_SUPER_MAGIC = 0x44534653 // zOS DSFS
NFS_SUPER_MAGIC = 0x6969 // NFS
NSFS_MAGIC = 0x6e736673 // PROCNS
PROC_SUPER_MAGIC = 0x9fa0 // proc FS
ZOSTFS_SUPER_MAGIC = 0x544653 // zOS TFS
ZOSUFS_SUPER_MAGIC = 0x554653 // zOS UFS
ZOSZFS_SUPER_MAGIC = 0x5A4653 // zOS ZFS
MTM_RDONLY = 0x80000000
MTM_RDWR = 0x40000000
MTM_UMOUNT = 0x10000000
@@ -205,13 +285,20 @@ const (
MTM_REMOUNT = 0x00000100
MTM_NOSECURITY = 0x00000080
NFDBITS = 0x20
ONLRET = 0x0020 // NL performs CR function
O_ACCMODE = 0x03
O_APPEND = 0x08
O_ASYNCSIG = 0x0200
O_CREAT = 0x80
O_DIRECT = 0x00002000
O_NOFOLLOW = 0x00004000
O_DIRECTORY = 0x00008000
O_PATH = 0x00080000
O_CLOEXEC = 0x00001000
O_EXCL = 0x40
O_GETFL = 0x0F
O_LARGEFILE = 0x0400
O_NDELAY = 0x4
O_NONBLOCK = 0x04
O_RDONLY = 0x02
O_RDWR = 0x03
@@ -248,6 +335,7 @@ const (
AF_IUCV = 17
AF_LAT = 14
AF_LINK = 18
AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
AF_MAX = 30
AF_NBS = 7
AF_NDD = 23
@@ -285,15 +373,33 @@ const (
RLIMIT_AS = 5
RLIMIT_NOFILE = 6
RLIMIT_MEMLIMIT = 7
RLIMIT_MEMLOCK = 0x8
RLIM_INFINITY = 2147483647
SCHED_FIFO = 0x2
SCM_CREDENTIALS = 0x2
SCM_RIGHTS = 0x01
SF_CLOSE = 0x00000002
SF_REUSE = 0x00000001
SHM_RND = 0x2
SHM_RDONLY = 0x1
SHMLBA = 0x1000
IPC_STAT = 0x3
IPC_SET = 0x2
IPC_RMID = 0x1
IPC_PRIVATE = 0x0
IPC_CREAT = 0x1000000
__IPC_MEGA = 0x4000000
__IPC_SHAREAS = 0x20000000
__IPC_BELOWBAR = 0x10000000
IPC_EXCL = 0x2000000
__IPC_GIGA = 0x8000000
SHUT_RD = 0
SHUT_RDWR = 2
SHUT_WR = 1
SOCK_CLOEXEC = 0x00001000
SOCK_CONN_DGRAM = 6
SOCK_DGRAM = 2
SOCK_NONBLOCK = 0x800
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
@@ -378,8 +484,6 @@ const (
S_IFMST = 0x00FF0000
TCP_KEEPALIVE = 0x8
TCP_NODELAY = 0x1
TCP_INFO = 0xb
TCP_USER_TIMEOUT = 0x1
TIOCGWINSZ = 0x4008a368
TIOCSWINSZ = 0x8008a367
TIOCSBRK = 0x2000a77b
@@ -427,7 +531,10 @@ const (
VSUSP = 9
VTIME = 10
WCONTINUED = 0x4
WEXITED = 0x8
WNOHANG = 0x1
WNOWAIT = 0x20
WSTOPPED = 0x10
WUNTRACED = 0x2
_BPX_SWAP = 1
_BPX_NONSWAP = 2
@@ -452,8 +559,30 @@ const (
MADV_FREE = 15 // for Linux compatibility -- no zos semantics
MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics
MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics
AT_SYMLINK_NOFOLLOW = 1 // for Unix compatibility -- no zos semantics
AT_FDCWD = 2 // for Unix compatibility -- no zos semantics
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
XATTR_CREATE = 0x1
XATTR_REPLACE = 0x2
P_PID = 0
P_PGID = 1
P_ALL = 2
PR_SET_NAME = 15
PR_GET_NAME = 16
PR_SET_NO_NEW_PRIVS = 38
PR_GET_NO_NEW_PRIVS = 39
PR_SET_DUMPABLE = 4
PR_GET_DUMPABLE = 3
PR_SET_PDEATHSIG = 1
PR_GET_PDEATHSIG = 2
PR_SET_CHILD_SUBREAPER = 36
PR_GET_CHILD_SUBREAPER = 37
AT_FDCWD = -100
AT_EACCESS = 0x200
AT_EMPTY_PATH = 0x1000
AT_REMOVEDIR = 0x200
RENAME_NOREPLACE = 1 << 0
ST_RDONLY = 1
ST_NOSUID = 2
)
const (
@@ -476,6 +605,7 @@ const (
EMLINK = Errno(125)
ENAMETOOLONG = Errno(126)
ENFILE = Errno(127)
ENOATTR = Errno(265)
ENODEV = Errno(128)
ENOENT = Errno(129)
ENOEXEC = Errno(130)
@@ -700,7 +830,7 @@ var errorList = [...]struct {
{145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."},
{146, "EDC5146I", "Too many levels of symbolic links."},
{147, "EDC5147I", "Illegal byte sequence."},
{148, "", ""},
{148, "EDC5148I", "The named attribute or data not available."},
{149, "EDC5149I", "Value Overflow Error."},
{150, "EDC5150I", "UNIX System Services is not active."},
{151, "EDC5151I", "Dynamic allocation error."},
@@ -743,6 +873,7 @@ var errorList = [...]struct {
{259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."},
{260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."},
{262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."},
{265, "EDC5265I", "The named attribute not available."},
{1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."},
{1001, "EDC8001I", "An error was found in the IUCV header."},
{1002, "EDC8002I", "A socket descriptor is out of range."},

364
vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s generated vendored Normal file
View File

@@ -0,0 +1,364 @@
// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build zos && s390x
#include "textflag.h"
// provide the address of function variable to be fixed up.
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Flistxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fremovexattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fgetxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fsetxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_accept4Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·accept4(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_RemovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Removexattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_Dup3Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Dup3(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_DirfdAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Dirfd(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EpollCreateAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·EpollCreate(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EpollCreate1Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·EpollCreate1(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EpollCtlAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·EpollCtl(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EpollPwaitAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·EpollPwait(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EpollWaitAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·EpollWait(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_EventfdAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Eventfd(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FaccessatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Faccessat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FchmodatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fchmodat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FchownatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fchownat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FdatasyncAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fdatasync(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_fstatatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·fstatat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Lgetxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Lsetxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FstatfsAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Fstatfs(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FutimesAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Futimes(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_FutimesatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Futimesat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_GetrandomAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Getrandom(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_InotifyInitAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·InotifyInit(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_InotifyInit1Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·InotifyInit1(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_InotifyAddWatchAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·InotifyAddWatch(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_InotifyRmWatchAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·InotifyRmWatch(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_ListxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Listxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Llistxattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Lremovexattr(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LutimesAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Lutimes(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_StatfsAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Statfs(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_SyncfsAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Syncfs(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_UnshareAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Unshare(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_LinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Linkat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_MkdiratAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Mkdirat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_MknodatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Mknodat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_PivotRootAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·PivotRoot(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_PrctlAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Prctl(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_PrlimitAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Prlimit(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_RenameatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Renameat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_Renameat2Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Renameat2(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_SethostnameAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Sethostname(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_SetnsAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Setns(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_SymlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Symlinkat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_UnlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·Unlinkat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_openatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·openat(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_openat2Addr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·openat2(SB), R8
MOVD R8, ret+0(FP)
RET
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
TEXT ·get_utimensatAddr(SB), NOSPLIT|NOFRAME, $0-8
MOVD $·utimensat(SB), R8
MOVD R8, ret+0(FP)
RET

View File

@@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func renamexNp(from string, to string, flag uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(from)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(to)
if err != nil {
return
}
_, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_renamex_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(from)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(to)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_renameatx_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer
if len(mib) > 0 {
@@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pthread_chdir_np(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_pthread_chdir_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pthread_fchdir_np(fd int) (err error) {
_, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_pthread_fchdir_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) {
var _p0 unsafe.Pointer
if len(iov) > 0 {
_p0 = unsafe.Pointer(&iov[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_connectx_trampoline_addr uintptr
//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) {
_, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags))
if e1 != 0 {

View File

@@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8
DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB)
TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_renamex_np(SB)
GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB)
TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_renameatx_np(SB)
GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB)
TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sysctl(SB)
GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8
DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB)
TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_pthread_chdir_np(SB)
GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB)
TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_pthread_fchdir_np(SB)
GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB)
TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_connectx(SB)
GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8
DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB)
TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sendfile(SB)
GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8

View File

@@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func renamexNp(from string, to string, flag uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(from)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(to)
if err != nil {
return
}
_, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_renamex_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(from)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(to)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_renameatx_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer
if len(mib) > 0 {
@@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pthread_chdir_np(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_pthread_chdir_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pthread_fchdir_np(fd int) (err error) {
_, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_pthread_fchdir_np_trampoline_addr uintptr
//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) {
var _p0 unsafe.Pointer
if len(iov) > 0 {
_p0 = unsafe.Pointer(&iov[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_connectx_trampoline_addr uintptr
//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) {
_, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags))
if e1 != 0 {

View File

@@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8
DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB)
TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_renamex_np(SB)
GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB)
TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_renameatx_np(SB)
GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB)
TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sysctl(SB)
GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8
DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB)
TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_pthread_chdir_np(SB)
GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB)
TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_pthread_fchdir_np(SB)
GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8
DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB)
TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_connectx(SB)
GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8
DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB)
TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sendfile(SB)
GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8

View File

@@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) {
_, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getdents(fd int, buf []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
@@ -2219,3 +2229,19 @@ func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Mseal(b []byte, flags uint) (err error) {
var _p0 unsafe.Pointer
if len(b) > 0 {
_p0 = unsafe.Pointer(&b[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall(SYS_MSEAL, uintptr(_p0), uintptr(len(b)), uintptr(flags))
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(fsType)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(dir)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_mount_trampoline_addr uintptr
//go:cgo_import_dynamic libc_mount mount "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
_, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
if e1 != 0 {

View File

@@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4
DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB)
TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_mount(SB)
GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4
DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB)
TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_nanosleep(SB)
GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4

View File

@@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(fsType)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(dir)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_mount_trampoline_addr uintptr
//go:cgo_import_dynamic libc_mount mount "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
_, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
if e1 != 0 {

View File

@@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8
DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB)
TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_mount(SB)
GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8
DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB)
TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_nanosleep(SB)
GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8

View File

@@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(fsType)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(dir)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_mount_trampoline_addr uintptr
//go:cgo_import_dynamic libc_mount mount "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
_, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
if e1 != 0 {

View File

@@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4
DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB)
TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_mount(SB)
GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4
DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB)
TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_nanosleep(SB)
GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4

View File

@@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(fsType)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(dir)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_mount_trampoline_addr uintptr
//go:cgo_import_dynamic libc_mount mount "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
_, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
if e1 != 0 {

View File

@@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8
DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB)
TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_mount(SB)
GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8
DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB)
TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_nanosleep(SB)
GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8

Some files were not shown because too many files have changed in this diff Show More