Since privileges work very differently on Unix-like systems and Windows, you need to have code on the platform. In any case, you need to split your program into two separate programs, one of which runs with higher permissions, and the other with standard / reduced permissions.
On Unix-like systems (including Linux and Mac OS X), an executable file that works with elevated privileges should do this:
- Suppose you are running root and open a file for reading. Since you mentioned that the file is very large, you are not actually reading the entire file, you just keep the handle of the open file. If it does not open, print an error message and exit.
- Use
setreuid(2) and setregid(2) to set the user id and group id back to the unprivileged user. - Use one of the
exec(3) functions to execute an unprivileged executable. - If you want to make it so that you can run this program without using
sudo , then make it root and make it set-user-ID executable using chown root the-program; chmod +s the-program chown root the-program; chmod +s the-program .
An unprivileged program will now run with normal permissions, but when it starts, it will have an open file descriptor (file descriptor No. 3), which you can use to read from your special file.
For Windows, this is similar, but slightly different:
- Suppose you are using root and open the file for reading using
CreateFile . Do not use the default security attributes - create a SECURITY_ATTRIBUTES structure with bInheritHandle set to TRUE so that the handle is inherited by child processes. If the file cannot be opened, print an error message and exit. - Use
CreateProcess to start the child process. Go to the descriptor above on the command line (for example, printed as a numeric value); you can also use the shared memory area , but this is more of a problem than it costs for this problem. - Paste the manifest into this executable with the
requireAdministrator set to TRUE . After that, when you run the program, you will receive a UAC prompt asking you to allow the program to make changes.
Then the child process captures the inherited descriptor, parsing the command line, and then it can read the data as it sees fit.
One of the problems with this approach is that when you inherit a descriptor, you need to use low level system calls ( read(2) on Unix, ReadFile on Windows) to read from it - you cannot use higher level functions like like C fread(3) or C ++ iostream (ok, Unix has fdopen(3) , but there is no equivalent on Windows as far as I know).
As Iβm sure, you have already noticed that everything above was in C. On Unix, this is pretty easy to translate to Python, since the os module has many goodies like setreuid , exec* and fdopen . On Windows, you can perform some of these actions with the ctypes and / or Pywin32 module , but maybe stick with C.