How to add space to formatting - string-formatting

Im new to coding, and found a script that writes the song and artist into a txt file called PlayLog.txt. When i use the script, it works as intended, however I do not know how to add space to the end of the output.
so instead of "[song] by [artist]" I would like "[song] by [artist] + 8 spaces"
that way the scrolling text in my OBS doesnt merge the end of the artist with the beginning of the song.
; This script displays the currently playing song from the pandora one app
;
; Any future updates can be found at http://notunusual.net/pandoraone_autohotkey/
;
; This function relies heavily on the excellent tray icon script by Sean, the original version
; of these functions can be found here - http://www.autohotkey.com/forum/topic17314.html
;
; Updates to the tray icon functions originally by Fanatic Guru, as per the following link:
; http://www.autohotkey.com/board/topic/94573-autohotkey-startup-consolidate-ahk-scripts-tray-icons/?p=595938
;
; Further updates to the tray icon functions and to this script in general by RiseUp.
; Make the script work even if the window is hidden
DetectHiddenWindows, on
; Only allow a single instance of the script
#SingleInstance
LogFileDir := A_AppData . "\notunusual\PandoraOne\"
LogFile := LogFileDir . "PlayLog.txt"
FileCreateDir, %LogFileDir%
if (ErrorLevel = 1)
{
MsgBox "Error creating directory!"
}
prevArtist := ""
prevSong := ""
while (true)
{
GetCurrentPlayingSong(curSong, curArtist)
if (((curSong <> prevSong) or (curArtist <> prevArtist)) and ((curSong <> "") and (curArtist <> "")))
{
prevSong := curSong
prevArtist := curArtist
FileDelete, %LogFile%
if ErrorLevel
MsgBox, Error deleting PlayLog.txt!
FileAppend %prevSong% by %prevArtist%, %LogFile%
}
; This is how often a check will be done, a sleep of 1000 means every 1 second we'll check the value
Sleep, 1000
}
; This returns the current song in the format Song by Artist, this can easily be changed to
; whatever format is desired
GetCurrentPlayingSong(ByRef songName, ByRef artist, space)
{
TI := TrayIconsSearch("Pandora.exe")
StringSplit,TIV, TI, |
toolTip := RegExReplace(TIV9, "Tooltip: ")
StringSplit, toolTipArray, toolTip, `n
songName := toolTipArray2
artist := RegExReplace( toolTipArray3, "by " )
}
TrayIconsSearch(sTerm)
{
Tray_Icons := {}
Tray_Icons := TrayIcons(sTerm)
if A_OSVersion in WIN_VISTA,WIN_7,WIN_8
{
arr := {}
arr := TrayIconsOverflow(sTerm)
for index, element in arr
Tray_Icons.Insert(element)
arr := ""
}
for index, element in Tray_Icons
sTrayIcons .= "idx: " . element.idx . " | idn: " . element.idn . " | Pid: " . element.pid . " | uID: " . element.uID . " | MessageID: " . element.MessageID . " | hWnd: " . element.hWnd . " | Class: " . element.Class . " | Process: " . element.Process . "`n" . " | Tooltip: " . element.Tooltip . "`n`n"
Return sTrayIcons
}
TrayIcons(sExeName = "")
{
arr := {}
Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, On
WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd
hProc:= DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
pProc:= DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
idxTB:= GetTrayBar()
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_BUTTONCOUNT
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETBUTTON
VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)
iBitmap := NumGet(btn, 0)
idn := NumGet(btn, 4)
Statyle := NumGet(btn, 8)
If dwData := NumGet(btn,12,"Uint")
iString := NumGet(btn,16)
Else dwData := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 32, "Uint", 0)
If NumGet(btn,12,"Uint")
hWnd := NumGet(nfo, 0)
, uID := NumGet(nfo, 4)
, nMsg := NumGet(nfo, 8)
, hIcon := NumGet(nfo,20)
Else hWnd := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8,"Uint"), nMsg:=NumGet(nfo,12,"Uint")
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
, DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString, "Uint", &wTooltip, "Uint", 128*2, "Uint", 0)
, DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
, Index = arr.MaxIndex()>0 ? arr.MaxIndex()+1 : 1
, arr[Index,"idx"] := A_Index-1
, arr[Index,"idn"] := idn
, arr[Index,"Pid"] := Pid
, arr[Index,"uID"] := uID
, arr[Index,"MessageID"] := nMsg
, arr[Index,"hWnd"] := hWnd
, arr[Index,"Class"] := sClass
, arr[Index,"Process"] := sProcess
, arr[Index,"Tooltip"] := (A_IsUnicode ? wTooltip : sTooltip)
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
Return arr
}
TrayIconsOverflow(sExeName = "")
{
arr := {}
Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, On
WinGet, pidTaskbar, PID, ahk_class NotifyIconOverflowWindow
hProc:= DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
pProc:= DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
idxTB:= 1
SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class NotifyIconOverflowWindow ; TB_BUTTONCOUNT
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class NotifyIconOverflowWindow ; TB_GETBUTTON
VarSetCapacity(btn,32,0), VarSetCapacity(nfo,32,0)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)
iBitmap := NumGet(btn, 0)
idn := NumGet(btn, 4)
Statyle := NumGet(btn, 8)
If dwData := NumGet(btn,12,"Uint")
iString := NumGet(btn,16)
Else dwData := NumGet(btn,16,"int64"), iString:=NumGet(btn,24,"int64")
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 32, "Uint", 0)
If NumGet(btn,12,"Uint")
hWnd := NumGet(nfo, 0)
, uID := NumGet(nfo, 4)
, nMsg := NumGet(nfo, 8)
, hIcon := NumGet(nfo,20)
Else hWnd := NumGet(nfo, 0,"int64"), uID:=NumGet(nfo, 8,"Uint"), nMsg:=NumGet(nfo,12,"Uint")
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
VarSetCapacity(sTooltip,128), VarSetCapacity(wTooltip,128*2)
, DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString, "Uint", &wTooltip, "Uint", 128*2, "Uint", 0)
, DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
, Index = arr.MaxIndex()>0 ? arr.MaxIndex()+1 : 1
, arr[Index,"idx"] := A_Index-1
, arr[Index,"idn"] := idn
, arr[Index,"Pid"] := Pid
, arr[Index,"uID"] := uID
, arr[Index,"MessageID"] := nMsg
, arr[Index,"hWnd"] := hWnd
, arr[Index,"Class"] := sClass
, arr[Index,"Process"] := sProcess
, arr[Index,"Tooltip"] := (A_IsUnicode ? wTooltip : sTooltip)
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
Return arr
}
GetTrayBar()
{
ControlGet, hParent, hWnd,, TrayNotifyWnd1 , ahk_class Shell_TrayWnd
ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
Loop
{
ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
If Not hWnd
Break
Else If hWnd = %hChild%
{
idxTB := A_Index
Break
}
}
Return idxTB
}

Well... I'll bite. Here's the code you need to modify.
FileAppend %prevSong% by %prevArtist%, %LogFile%
Here's how I would modify it.
NewVar := prevSong . " by " . prevArtist . " "
FileAppend %NewVar%, %LogFile%
FYI, there were examples of this method in the code itself if you studied it for a moment you would see it.

Related

X11 Shift + Tab keysym?

How to detect Shift + Tab in Xlib? I'm able to match KeySym with XK_Tab, but it's not matching while holding shift to then check for ev->state & ShiftMask, so I'm kind of lost.
SOLUTION:
Thanks to Erdal Küçük's answer I was able to come up with the following function that detects Shift + Tab:
int detectShiftTab(XKeyEvent *xkey) {
return XLookupKeysym(xkey, 0) == XK_Tab && xkey->state & ShiftMask;
}
With a simple test, i realized that the ShiftMask is not reported on a KeyPress of the Shift key. Other than that, the ShiftMask is always set.
int main()
{
Display *dpy = XOpenDisplay(NULL);
Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 640, 480, 0, 0, 0);
XSetWindowAttributes attr = { .event_mask = (KeyPressMask | KeyReleaseMask) };
XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
XMapWindow(dpy, win);
while (1) {
XEvent evt;
XNextEvent(dpy, &evt);
switch (evt.type) {
case KeyPress:
printf(
"key press: %s shiftmask: %d\n",
XKeysymToString(XLookupKeysym(&evt.xkey, 0)),
(evt.xkey.state & ShiftMask) == ShiftMask
);
break;
case KeyRelease:
printf(
"key release: %s shiftmask: %d\n",
XKeysymToString(XLookupKeysym(&evt.xkey, 0)),
(evt.xkey.state & ShiftMask) == ShiftMask
);
break;
}
}
return 0;
}
I get the following output (typing Shift + Tab):
key press: Shift_L shiftmask: 0
key press: Tab shiftmask: 1
key release: Tab shiftmask: 1
key release: Shift_L shiftmask: 1

why doesn't the OpenCL kernel execute even though there are no errors? (c, nvidia, kubuntu)

I'm learning opencl and for some reason the kernel does nothing:
#include <stdlib.h>
#include <stdio.h>
#define CL_TARGET_OPENCL_VERSION 300
#include <CL/cl.h>
int err = 0;
#define PRINTERR() fprintf(stderr, "Error at line %u.\n", __LINE__)
#define CHECKERR(x) if(x){PRINTERR();return __LINE__;}
#define CHECKNOTERR(x) if(!x){PRINTERR();return __LINE__;}
const char *KernelSource =
"__kernel void square( \n" \
" __global float* input, \n" \
" __global float* output, \n" \
" const unsigned int count) \n" \
"{ \n" \
" int i = get_global_id(0); \n" \
" if(i == 0) printf(\"test\\n\"); \n" \
" if(i < count) \n" \
" output[i] = input[i] * input[i]; \n" \
"} \n" ;
#define DATA_SIZE 1024
int main(){
float data[DATA_SIZE];
float results[DATA_SIZE];
size_t global;
size_t local;
cl_platform_id platform_id;
cl_device_id device_id;
cl_context context;
cl_command_queue commands;
cl_program program;
cl_kernel kernel;
cl_mem input;
cl_mem output;
unsigned int i = 0;
unsigned int count = DATA_SIZE;
for(i = 0; i < count; ++i)
//data[i] = rand() / (float)RAND_MAX;
data[i] = 2.f;
int gpu = 1;
err = clGetPlatformIDs (1, &platform_id, NULL); CHECKERR(err)
err = clGetDeviceIDs(platform_id, gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU, 1, &device_id, NULL); CHECKERR(err)
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &err); CHECKERR(!context)
commands = clCreateCommandQueueWithProperties(context, device_id, NULL, &err); CHECKERR(err)
input = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(float) * count, NULL, &err); CHECKERR(err)
output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * count, NULL, &err); CHECKERR(err)
CHECKERR(!input || !output)
err = clEnqueueWriteBuffer(commands, input, CL_TRUE, 0, sizeof(float) * count, data, 0, NULL, NULL); CHECKERR(err)
program = clCreateProgramWithSource(context, 1, &KernelSource, NULL, &err); CHECKERR(err)
err = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); CHECKERR(err)
kernel = clCreateKernel(program, "square", &err); CHECKERR(err)
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input);
err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &output);
err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &count);
CHECKERR(err)
err = clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL); CHECKERR(err)
err = clEnqueueNDRangeKernel(commands, kernel, 1, NULL, &global, &local, 0, NULL, NULL); CHECKERR(err)
err = clEnqueueReadBuffer(commands, output, CL_TRUE, 0, sizeof(float) * count, results, 0, NULL, NULL ); CHECKERR(err)
clFlush(commands);
clFinish(commands);
unsigned int correct = 0;
for(i = 0; i < count; ++i)
printf("%f\n",results[i]);
printf("Computed '%d/%d' correct values!\n", correct, count);
// free
clReleaseMemObject(input);
clReleaseMemObject(output);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(commands);
clReleaseContext(context);
return 0;
}
i want it to do things, but it doesn't.
i tried reading the input instead of the output and it goes fine. the printf in the kernel does nothing and if i run it clEnqueueReadBuffer gives just 0. i have an amd, so i can't test it on the cpu.
i tried another example and it worked. (the one here)
help appreciated.
global is 0, so the program runs 0 times.

How do I fix a CL_INVALID_MEM_OBJECT when I pass a buffer to an OpenCL kernel and the buffer is from clCreateFromGLTexture?

I need to do some math on the pixels of a GL texture. I have a working OpenCL kernel. I can convert the GL texture to an OpenCL buffer (at least, it doesn't give an error). But when I try to set that buffer as an argument to the kernel I get error -38 (CL_INVALID_MEM_OBJECT).
I originally tried it using rust, but when that was failing, I switched to C just to see if the problem existed independent of rust's wrappers.
This is my C app that is duct taped together from a couple of examples (c++ -g -o check2 check2.cxx -lOpenCL -lGL -lX11):
/*
https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <CL/cl.h>
#include <CL/cl_gl.h>
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
// Helper to check for extension string presence. Adapted from:
// http://www.opengl.org/resources/features/OGLextensions/
static bool isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if (where || *extension == '\0')
return false;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for (start=extList;;) {
where = strstr(start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '\0' )
return true;
start = terminator;
}
return false;
}
static bool ctxErrorOccurred = false;
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
ctxErrorOccurred = true;
return 0;
}
void test_kernel(cl_mem a_mem_obj, cl_mem b_mem_obj, cl_mem c_mem_obj, cl_kernel kernel, int LIST_SIZE, cl_command_queue command_queue)
{
int err;
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\tset kernel arg 0\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy result)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
}
int main(int argc, char* argv[])
{
Display *display = XOpenDisplay(NULL);
if (!display)
{
printf("Failed to open X display\n");
exit(1);
}
// Get a matching FB config
static int visual_attribs[] =
{
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
//GLX_SAMPLE_BUFFERS , 1,
//GLX_SAMPLES , 4,
None
};
int glx_major, glx_minor;
// FBConfigs were added in GLX version 1.3.
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
{
printf("Invalid GLX version");
exit(1);
}
printf( "Getting matching framebuffer configs\n" );
int fbcount;
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
if (!fbc)
{
printf( "Failed to retrieve a framebuffer config\n" );
exit(1);
}
printf( "Found %d matching FB configs.\n", fbcount );
// Pick the FB config/visual with the most samples per pixel
printf( "Getting XVisualInfos\n" );
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
int i;
for (i=0; i<fbcount; ++i)
{
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
if ( vi )
{
int samp_buf, samples;
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
printf( " Matching fbconfig %d, visual ID 0x%2lx: SAMPLE_BUFFERS = %d,"
" SAMPLES = %d\n",
i, vi -> visualid, samp_buf, samples );
if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
best_fbc = i, best_num_samp = samples;
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
worst_fbc = i, worst_num_samp = samples;
}
XFree( vi );
}
GLXFBConfig bestFbc = fbc[ best_fbc ];
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
XFree( fbc );
#if 0
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%lx\n", vi->visualid );
printf( "Creating colormap\n" );
XSetWindowAttributes swa;
Colormap cmap;
swa.colormap = cmap = XCreateColormap( display,
RootWindow( display, vi->screen ),
vi->visual, AllocNone );
swa.background_pixmap = None ;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
printf( "Creating window\n" );
Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
0, 0, 100, 100, 0, vi->depth, InputOutput,
vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa );
if ( !win )
{
printf( "Failed to create window.\n" );
exit(1);
}
// Done with the visual info data
XFree( vi );
XStoreName( display, win, "GL 3.0 Window" );
printf( "Mapping window\n" );
XMapWindow( display, win );
#endif
// Get the default screen's GLX extension list
const char *glxExts = glXQueryExtensionsString( display,
DefaultScreen( display ) );
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
GLXContext ctx = 0;
// Install an X error handler so the application won't exit if GL 3.0
// context allocation fails.
//
// Note this error handler is global. All display connections in all threads
// of a process use the same error handler, so be sure to guard against other
// threads issuing X commands while this code is running.
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
!glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
}
// If it does, try to get a GL 3.0 context!
else
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
// Sync to ensure any errors generated are processed.
XSync( display, False );
if ( !ctxErrorOccurred && ctx )
printf( "Created GL 3.0 context\n" );
else
{
// Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
// When a context version below 3.0 is requested, implementations will
// return the newest context version compatible with OpenGL versions less
// than version 3.0.
// GLX_CONTEXT_MAJOR_VERSION_ARB = 1
context_attribs[1] = 1;
// GLX_CONTEXT_MINOR_VERSION_ARB = 0
context_attribs[3] = 0;
ctxErrorOccurred = false;
printf( "Failed to create GL 3.0 context"
" ... using old-style GLX context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
}
}
// Sync to ensure any errors generated are processed.
XSync( display, False );
// Restore the original error handler
XSetErrorHandler( oldHandler );
if ( ctxErrorOccurred || !ctx )
{
printf( "Failed to create an OpenGL context\n" );
exit(1);
}
// Verifying that context is a direct context
if ( ! glXIsDirect ( display, ctx ) )
{
printf( "Indirect GLX rendering context obtained\n" );
}
else
{
printf( "Direct GLX rendering context obtained\n" );
}
printf( "Making context current\n" );
glXMakeCurrent( display, 0, ctx );
#define IMAGE_DIAM 512
#define LIST_SIZE (IMAGE_DIAM*IMAGE_DIAM*3)
GLuint texture_id;
{
glGenTextures(1, &texture_id);
printf("err? %d\n", glGetError());
glBindTexture(GL_TEXTURE_2D, texture_id);
printf("err? %d\t(bind texture)\n", glGetError());
unsigned char random_stack_crap[LIST_SIZE];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, IMAGE_DIAM, IMAGE_DIAM, 0, GL_RGB, GL_UNSIGNED_BYTE, random_stack_crap);
printf("err? %d\n", glGetError());
}
//
//
//
cl_platform_id platform;
clGetPlatformIDs(1, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
printf("device\t%p\n", device);
printf ("context\t%p\t%p\n", ctx, glXGetCurrentContext());
printf ("display\t%p\t%p\n", display, glXGetCurrentDisplay());
cl_context_properties props[] =
{
CL_GL_CONTEXT_KHR,
(cl_context_properties) glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR,
(cl_context_properties) glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM,
(cl_context_properties) platform,
0
};
int err=0;
cl_context cl = clCreateContext(props, 1, &device, NULL, NULL, &err);
printf("err? %d\n", err);
printf("cl context %p\n", cl);
//
// https://www.eriksmistad.no/getting-started-with-opencl-and-gpu-computing/
//
cl_command_queue command_queue = clCreateCommandQueue(cl, device, 0, &err);
printf("err? %d\n", err);
printf("cl queue %p\n", command_queue);
// Create memory buffers on the device for each vector
cl_mem z_mem_obj = clCreateFromGLTexture( cl,
CL_MEM_READ_WRITE,
GL_TEXTURE_2D,
0,
texture_id,
&err);
cl_mem a_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem b_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem c_mem_obj = clCreateBuffer(cl, CL_MEM_WRITE_ONLY,
LIST_SIZE*8 , NULL, &err);
printf("err? %d\n", err);
// Copy the lists A and B to their respective memory buffers
{
unsigned char *A = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
A[i] = i+2;
}
unsigned char *B = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
B[i] = 2*i;
}
err = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0,
LIST_SIZE, A, 0, NULL, NULL);
printf("err? %d\tcopy A\n", err);
err = clEnqueueWriteBuffer(command_queue, b_mem_obj, CL_TRUE, 0,
LIST_SIZE, B, 0, NULL, NULL);
printf("err? %d\tcopy B\n", err);
}
const char* source_str = "__kernel void diff(__global uchar* rgb_a, __global uchar* rgb_b, __global ulong * diff_out)\n\
{\n\
int idx = get_global_id(0);\n\
diff_out[idx] = abs((int)rgb_a[idx] - (int)rgb_b[idx]);\n\
}";
size_t source_size = strlen(source_str);
// Create a program from the kernel source
cl_program program = clCreateProgramWithSource(cl, 1,
(const char **)&source_str, (const size_t *)&source_size, &err);
printf("err? %d\t(create program)\n", err);
// Build the program
err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
printf("err? %d\n", err);
// Create the OpenCL kernel
cl_kernel kernel = clCreateKernel(program, "diff", &err);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy resul)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
test_kernel(a_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
test_kernel(z_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
return 0;
}
The output on my linux/gentoo box with mesa-progs-8.4.0 is
Getting matching framebuffer configs
Found 10 matching FB configs.
Getting XVisualInfos
Matching fbconfig 0, visual ID 0x24: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 1, visual ID 0x7a: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 2, visual ID 0x38: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 3, visual ID 0x8e: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 4, visual ID 0x3a: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 5, visual ID 0x90: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 6, visual ID 0x44: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 7, visual ID 0x9a: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 8, visual ID 0x4c: SAMPLE_BUFFERS = 1, SAMPLES = 16
Matching fbconfig 9, visual ID 0xa2: SAMPLE_BUFFERS = 1, SAMPLES = 16
Creating context
Created GL 3.0 context
Direct GLX rendering context obtained
Making context current
err? 0
err? 0 (bind texture)
err? 0
device 0x557c1755cef0
context 0x557c173e0b68 0x557c173e0b68
display 0x557c172ee950 0x557c172ee950
err? 0
cl context 0x557c17559340
err? 0
cl queue 0x557c177dd080
err? 0
err? 0
err? 0
err? 0 copy A
err? 0 copy B
err? 0 (create program)
err? 0
err? 0
err? 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy resul)
2
1
0
1
2
3
4
5
6
7
err? 0 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
err? -38 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
Notice the err? -38 set kernel arg 0 which corresponds to the final test where I pass z_mem_obj to use the buffer converted from a GL texture.
clinfo | grep khr lists cl_khr_gl_sharing in the Platform Extensions and Device Extensions.

nvidia opengl framebuffer object forces vsync on

Basically I implemented gamma correction into a q3 based game to get rid of the annoying SetDeviceGammaRamp.
I'm using GL_EXT_framebuffer_object for a post process vertex shader.
It works pretty fine except that it has some weird behavior on nvidia gpus:
It forces vsync to be enabled except when it is explicitly disabled in the control panel. If I use the standard control panel's settings and the framebuffer is enabled vsync is forced, but if I remove the framebuffer it goes back to normal behavior.
wglSwapIntervalEXT does nothing
I tested it on an nvidia mobile GPU, someone could reproduce it on a desktop GPU
I also tested an integrated intel gpu and two different amd gpu's and all of them didn't have the issue.
initialization: (unrelevant i guess)
// ouned: gamma correction
const char *g_GammaVertexShaderARB = {
"void main(void)" "\n"
"{" "\n"
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" "\n"
"gl_TexCoord[0] = gl_MultiTexCoord0;" "\n"
"}"
};
const char *g_GammaFragmentShaderARB = {
"uniform sampler2D sceneBuffer;" "\n"
"uniform float gamma;" "\n"
"\n"
"void main(void)" "\n"
"{" "\n"
"vec2 uv = gl_TexCoord[0].xy;" "\n"
"vec3 color = texture2D(sceneBuffer, uv).rgb;" "\n"
"if (uv.x<0.50)" "\n"
"gl_FragColor.rgb = pow(color, vec3(1.0 / 1.5));" "\n"
"else" "\n"
"gl_FragColor.rgb = color;" "\n"
"gl_FragColor.a = 1.0;" "\n"
"}"
};
tr.m_hVShader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
qglShaderSourceARB(tr.m_hVShader, 1, (const GLcharARB **)&g_GammaVertexShaderARB, NULL);
qglCompileShaderARB(tr.m_hVShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma vertrex shader\n");
}
tr.m_hFShader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
qglShaderSourceARB(tr.m_hFShader, 1, (const GLcharARB **)&g_GammaFragmentShaderARB, NULL);
qglCompileShaderARB(tr.m_hFShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma fragment shader\n");
}
tr.gammaProgram = qglCreateProgramObjectARB();
qglAttachObjectARB(tr.gammaProgram, tr.m_hVShader);
qglAttachObjectARB(tr.gammaProgram, tr.m_hFShader);
qglLinkProgramARB(tr.gammaProgram);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed linking shaders\n");
}
qglUseProgramObjectARB(tr.gammaProgram);
tr.gammaUniformLoc = qglGetUniformLocationARB(tr.gammaProgram, "gamma");
tr.gammaSceneBufferLoc = qglGetUniformLocationARB(tr.gammaProgram, "sceneBuffer");
qglValidateProgramARB(tr.gammaProgram);
qglUseProgramObjectARB(0);
// framebuffer object
tr.gammaFramebuffer = 0;
qglGenFramebuffersEXT(1, &tr.gammaFramebuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
// depth buffer
tr.gammaRenderDepthBuffer = 0;
qglGenRenderbuffersEXT(1, &tr.gammaRenderDepthBuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, glConfig.vidWidth, glConfig.vidHeight);
tr.gammaRenderTarget = 0;
qglGenTextures(1, &tr.gammaRenderTarget);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglGenerateMipmapEXT(GL_TEXTURE_2D);
qglBindTexture(GL_TEXTURE_2D, 0);
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tr.gammaRenderTarget, 0);
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
On the beginning of a frame:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
on the end of a frame:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
if (!backEnd.projection2D) {
qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity();
qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity();
GL_State(GLS_DEPTHTEST_DISABLE);
}
qglUseProgramObjectARB(tr.gammaProgram);
qglEnable(GL_TEXTURE_2D);
qglUniform1iARB(tr.gammaSceneBufferLoc, 0);
qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);
qglActiveTextureARB(GL_TEXTURE0);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglBegin(GL_QUADS);
qglTexCoord2f(0, 1);
qglVertex2f(0, 0);
qglTexCoord2f(1, 1);
qglVertex2f(glConfig.vidWidth, 0);
qglTexCoord2f(1, 0);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(0, 0);
qglVertex2f(0, glConfig.vidHeight);
qglEnd();
qglUseProgramObjectARB(0);
So, what else can cause vsync to be enabled?

losing capabilities after setuid()

Trying to set cap_setgid,cap_setuid,cap_setpcap.
#include <sys/types.h>
#include <sys/capability.h>
int main()
{
cap_t caps;
caps = cap_get_proc();
cap_value_t cap_list[2];
cap_list[0] = CAP_SETUID;
cap_list[1] = CAP_SETGID;
cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET);
cap_set_flag(caps, CAP_INHERITABLE, 2, cap_list, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
setgid(65534);
setuid(65534);
cap_get_proc();
setgid(0);
setuid(0);
return 0;
}
Execution is going under root user.
Tracing the program shows this
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 0, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0) = -1 EPERM (Operation not permitted)
setuid(0) = -1 EPERM (Operation not permitted)
exit_group(0) = ?
+++ exited with 0 +++
Privileges are set but do not work. Any suggestions how to solve this problem?
UPDATE: prctl added to code
21a22
> prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
24a26
> cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
so now it is
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
setgid(65534);
setuid(65534);
cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
Caps were inherited after setuid, and caps that were set manually are still there, but it didn't solve the problem
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0) = -1 EPERM (Operation not permitted)
setuid(0) = -1 EPERM (Operation not permitted)
exit_group(0) = ?
+++ exited with 0 +++
UPDATE2:
Can't understand it. Ive added 2strs after 1st setuid, to check out for caps.
printf("cape set %d\n", cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET));
printf("%s\n", cap_to_text(cap_get_proc(), NULL));
it returned
catp set 0
=p cap_setgid,cap_setuid,cap_setpcap+i
Effective flag is not set, but cap_set_flag returned 0
By default, capability sets are lost across an UID transition; use
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
to retain permitted capabilities (cap_set_flag(caps, CAP_PERMITTED, ...)). Note that the effective capability set will be reset, but can be re-established.
The following works fine for me.
#include <sys/capability.h>
#include <sys/prctl.h>
#include <unistd.h>
int main(int argc, char **argv) {
cap_value_t cap_values[] = {CAP_SETUID, CAP_SETGID};
cap_t caps;
caps = cap_get_proc();
cap_set_flag(caps, CAP_PERMITTED, 2, cap_values, CAP_SET);
cap_set_proc(caps);
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
cap_free(caps);
setgid(65534);
setuid(65534);
caps = cap_get_proc();
cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
setgid(0);
setuid(0);
return 0;
}
$ sudo strace ./a.out
...
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
prctl(PR_SET_KEEPCAPS, 1) = 0
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_SETGID|CAP_SETUID, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
setgid(0) = 0
setuid(0) = 0
...
I think you confused CAP_PERMITTED set with CAP_INHERITABLE,
Unless you are using threads/exec , you want to use CAP_PERMITTED.
Inheritable (formerly known as allowed):
This set is ANDed with the thread's inheritable set to determine which inheritable capabilities are enabled in the
permitted set of the thread after the execve(2)
As for update2: try printing out cap_to_text(cap_get_proc()) before/after and also consider what is the difference between cap_set_flag and cap_set_proc.

Resources