Determine current user temp directory on macOS - macos

How to print specific user temp directory in macOS? It should be able to determine the temp dir depending on which user is currently logged in. I see that my current user temp dir is set to /Users/myuser/private/tmp but i have no generic way to get hold of this
Googled a bit and it recommeds using $TMPDIR but looks like my user temp dir is somewhat set to /Users/myuser/private/tmp
I should be able to determine the exact tmp directory whether the current user is root or other user

Related SO question and answer, cross-platform: Cross-platform way of getting temp directory in Python
It's pretty generic.
In Qt5:
#include <QCoreApplication>
#include <QTemporaryDir>
#include <QDebug>
int main(int argc, char *argv[])
{
QTemporaryDir dir;
if (dir.isValid()) {
// dir.path() returns the unique directory path
qDebug() << "Path name: " << dir.path() ;
}
}
Also pretty generic.
In bash (terminal or script): echo $TMPDIR
The /var/folders/ is user-specific because if you run ls -l /var/folders/.../ (right before the -Tmp- directory, you will see that the folder is owned by the logged in user. If another user is logged in, their folder is protected by their permissions/ownership and they won't be able to read/modify another users' data. I suggest looking into unix/linux/mac file and folder permissions if you want to know more.
new-host-2:Applications ThisIsMe$ ls -l /var/folders/cp/cpI9fK8qG3y4x4sedjGIOE+++TI/
total 0
drwx------ 16 ThisIsMe staff 544 Jan 6 22:12 -Caches-
drwx------ 11 ThisIsMe staff 374 Jan 6 22:56 -Tmp-
http://www.filepermissions.com/articles/what-are-file-permissions-in-linux-and-mac
https://www.linux.com/tutorials/understanding-linux-file-permissions/

Related

Avoiding problems with gpg-agent when running from scripts - gpg2

I'm trying to use gpg to --clearsign a file (for debian packaging purposes) from a script.
I have an exported password-less private-key.gpg file and want to:
gpg --clearsign -o output input
I don't want to mess with the current user's ~/.gnupg or /run/user/$(id -u)/gnupg because they have nothing to do with my script. Also, the script could be running in multiple instances simultaneously and I don't want them interfering with one another.
I thought that would be easy. Setup $GNUPGHOME to a temp dir and be done with it. But I cannot figure out how to get gpg to run in a script without messing with the user's standard configuration at all. It seems gpg has gone to great lengths to make it impossible to avoid the gpg-agent and gpg-agent insists on using global/hard-coded paths.
Can I keep everything under $GNUPGHOME? Or how do I safely use gpg from a shell script without influencing the user's config or use of gpg or other instances of my script?
Details
Reading the gpg docs I see that:
--use-agent
--no-use-agent
This is dummy option. gpg always requires the agent.
And gpg-agent docs say:
--use-standard-socket
--no-use-standard-socket
--use-standard-socket-p
Since GnuPG 2.1 the standard socket is always used.
These options have no more effect. The command gpg-agent
--use-standard-socket-p will thus always return success.
This "standard socket" is presumably in /run/user/$(id -u)/gnupg - so it seems I can't avoid gpg messing with the user's "normal" use of gpg.
Versions: gpg 2.1.18 on Debian 9 / stretch / stable
If you can't stop gpg from creating files, would it help to give gpg a place to put them that's unique to the current process?
# Create a temporary directory for gpg.
dir="$(mktemp -d)"
# Remove the directory and its contents when the script exits.
trap '[[ ! -d "${dir}" ]] || rm -r "${dir}"' EXIT
# Put your private-key.gpg in the temporary directory.
$(your command here)
# Tell gpg to use the temporary directory.
gpg --homedir "${dir}" --clearsign -o output input
After multiple hours of searching the internet for some option to enable running multiple instances of gpg-agent with different gnupg homes I tried just restricting the access to the global socket location and it worked. It fell back to placing the socket files in the gnupg home directory. I used bwrap to do that. Here's the full command that worked: bwrap --dev-bind / / --tmpfs /run/user/$(id -u)/gnupg gpg-agent .... Since your question is about scripts in general, you probably can't rely on bwrap being installed, so the next best thing is a shim that prevents gpg-agent from using the user's xdg runtime directory for its sockets.
After looking through the output of strace, the switch of location when running under bwrap to gnupg home seems to happen after a stat on /run/user/${UID}/gnupg is issued. Looking through the gpg-agent.c code this seems to do that check:
/* Check that it is a directory, owned by the user, and only the
* user has permissions to use it. */
if (!S_ISDIR(sb.st_mode)
|| sb.st_uid != getuid ()
|| (sb.st_mode & (S_IRWXG|S_IRWXO)))
{
*r_info |= 4; /* Bad permissions or not a directory. */
if (!skip_checks)
goto leave;
}
Using this we can just tell gpg-agent that the /run/user/${UID}/gnupg exists, but is not a directory, so it will fail the first of these checks.
Here's the code for a shim that does just that (could be better, but it works):
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <stdio.h>
#define STR_MAX 4096
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
// Set up checking stuff
#define MAX_UID_LEN 11
#define PREFIX_1 "/run/user"
#define PREFIX_2 "/var/run/user"
#define TEST_LEN_1 (sizeof(PREFIX_1) - 1 + 1 + MAX_UID_LEN + sizeof("/gnupg") - 1)
#define TEST_LEN_2 (sizeof(PREFIX_2) - 1 + 1 + MAX_UID_LEN + sizeof("/gnupg") - 1)
#define MAX_TEST_LEN MAX(TEST_LEN_1, TEST_LEN_2)
// Override stat function
int stat(const char *restrict pathname, struct stat *restrict statbuf) {
int (*original_stat)(const char *restrict, struct stat *restrict) = dlsym(RTLD_NEXT, "stat");
// Call original stat function
int retval = original_stat(pathname, statbuf);
if (retval == 0) {
// Check if a path we want to modify
size_t pathlen = strnlen(pathname, STR_MAX);
char path_check[MAX_TEST_LEN + 1];
snprintf(path_check, MAX_TEST_LEN + 1, "%s/%u/gnupg", PREFIX_1, getuid());
if (strncmp(pathname, path_check, MIN(MAX_TEST_LEN, pathlen)) == 0) {
// Report a regular file with perms: rwxrwxrwx
statbuf->st_mode = S_IFREG|0777;
}
snprintf(path_check, MAX_TEST_LEN + 1, "%s/%u/gnupg", PREFIX_2, getuid());
if (strncmp(pathname, path_check, MIN(MAX_TEST_LEN, pathlen)) == 0) {
// Report a regular file with perms: rwxrwxrwx
statbuf->st_mode = S_IFREG|0777;
}
}
return retval;
}
You can compile it with: clang -Wall -O2 -fpic -shared -ldl -o gpg-shim.so gpg-shim.c and then add it to LD_PRELOAD and it should then allow you to run multiple gpg-agents as long as they have different gnupg homes.
I know this answer is really late, but I hope it can help some people that were, like me, looking for a way to run multiple gpg-agents with different homedirs. (For my specific case, I wanted to run multiple gpg-agent instances to have keys cached different amounts of time).

setuid flag doesn't change the effective userid

Here I have a file called uid_demo.c, which displays the real userid and the effective userid.
#include <stdio.h>
int main() {
printf("real uid: %d\n", getuid());
printf("effective uid: %d\n", geteuid());
}
And I ran the following commands:
gcc -o uid_demo uid_demo.c
sudo chown root:root ./uid_demo
sudo chmod u+s ./uid_demo
ls -l uid_demo
Output:
-rwsrwxr-x 1 root root 8712 Jun 29 15:09 uid_demo
When I run the program, it should display my real userid (1000) and the effective userid of 0 (root), as the owner of the file is root and the setuid permission is turned on. However, it displays the following:
real uid: 1000
effective uid: 1000
Any help? Thanks in advance.
You are probably running the program on a filesystem that is mounted wit the nosuid flag, thus your setuid bit is not respected.
Move your code to another location on the filesystem that does not have this, or disable the nosuid flag in the mount options for the current filesystem.
The nosuid flag is a security feature.

Recursively searching a directory without changing directory atimes

I'm checking an alternative to 'find' command in shell scripting so as to eliminate the discrepancy of Accessed date of sub directories.
According to my observation, when find command is executed to list all the files in a directory, the accessed date of sub-directories is getting changed.
I want to post genuine statistics in one of the junk platforms, So I have been looking at some forums and got the alternative with 'ls' command. But that doesn't completely fulfill my request.
Below is the answer given by #ghostdog74.
ls -R %path% | awk '/:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }'.
But this finds only the files inside the sub directories. I need all the files and sub-directories' files to be listed.
For example:
bash-3.2# pwd
/Users/manojkapalavai/Desktop/SleepTimeReport
bash-3.2# ls
**6th floor** manoj17 manoj26.txt manoj36 manoj45.txt manoj55 manoj70.txt manoj80 manoj9.txt **test1**
manoj14 manoj23.txt manoj33 manoj42.txt manoj52 manoj61.txt manoj71 manoj80.txt manoj90 **test2**.
The highlighted ones are sub-directories inside "SleepTimeReport" directory and remaining are just files. So, when I execute the above command, I get only the below output.
bash-3.2# ls -R ~/Desktop/SleepTimeReport | awk '/:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }'.
~/Desktop/SleepTimeReport/6th floor/Script to increase the Sleep Time.numbers.
~/Desktop/SleepTimeReport/6th floor/Zone1Sleep.pages.
~/Desktop/SleepTimeReport/test1/New_folder.
~/Desktop/SleepTimeReport/test1/manoj.txt.
~/Desktop/SleepTimeReport/test1/sathish.txt.
~/Desktop/SleepTimeReport/test1/vara.txt.
~/Desktop/SleepTimeReport/test1/New_folder/Script to increase the Sleep Time.numbers.
~/Desktop/SleepTimeReport/test1/New_folder/Zone1Sleep.pages.
i.e.; only those files inside sub-directories are listed.
Brief explanation of what issue I'm facing, please see below
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ ls -l
total 16
drwxr-xr-x 8 manojkapalavai staff 272 Sep 14 15:07 6th floor
-rwxr-xr-x 1 manojkapalavai staff 59 Nov 13 10:41 AltrFind.sh
-rw-r--r-- 1 manojkapalavai staff 0 Nov 2 15:15 manoj%.txt
-rw-r--r-- 1 manojkapalavai staff 0 Nov 2 18:23 manoj1
When I try finding Created time and Accessed Time of the folder 6th floor before using 'find' command, the below is output.
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ stat -f '%N, %SB, %Sa' 6th\ floor/
6th floor/, Sep 13 10:34:55 2017, **Nov 13 11:21:33 2017**
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ find /Users/manojkapalavai/Desktop/SleepTimeReport/
/Users/manojkapalavai/Desktop/SleepTimeReport/
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/.DS_Store
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/Script to increase the Sleep Time.numbers
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/Zone1Sleep.pages
Now, after finding all the files inside a directory, below is the output of atime. you can notice the change
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ stat -f '%N, %SB, %Sa' 6th\ floor/
6th floor/, Sep 13 10:34:55 2017, **Nov 13 14:26:03 2017**
All tha I have done is just find the files, and atime of sub-folders inside a folder when we find is getting changed to that current time.
Is there any way to solve this?
ls is the wrong tool for programmatic use. Generally, you should be able to fix your find usage to not have an effect on atimes (actually, it's pretty rare for folks to even have atimes enabled at the filesystem level on modern production systems), but if you really want to avoid it, consider the bash globstar option:
shopt -s globstar
for file in **/*; do
echo "Doing whatever with $file"
done

Windows API to access case-sensitive paths (Bash-on-Ubuntu-on-Windows)

Bash-on-Ubuntu-on-Windows supports case-sensitive file paths. This means that I can create two files or directories with names only differing in capitalization. I have issues accessing those files, though.
Running
bash -c "touch Magic ; mkdir magic ; echo Secret! > magic/secret"
Creates a file names Magic, a directory named magic and a file names secret in that directory.
bash -c "ls -lR" yields
.:
total 0
drwxrwxrwx 2 root root 0 Aug 23 10:37 magic
-rwxrwxrwx 1 root root 0 Aug 23 10:37 Magic
./magic:
total 0
-rwxrwxrwx 1 root root 8 Aug 23 10:37 secret
(I am not sure why I get root, as it is not the default user, but that does not seem relevant to my question.)
Windows Explorer shows:
Now, while bash can easily access the magic/secret file in the directory, Windows seems to treat both the directory and the file as one and the same. So double-clicking the directory I get a "directory name invalid" error
Same goes for using cd, as I get The directory name is invalid. printed out.
Are there any APIs that allow me to access those case-sensitive paths, or create them? It seems that regular Windows APIs ignore character case completely when accessing existing files.
Case-sensitive paths can be used on Windows with NTFS, but it requires a bit of extra work.
First, case-sensitivity must be enabled system-wide. This is done by setting the HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ dword:ObCaseInsensitive registry value to 0, then restarting the system.
I found this part here.
Once case-sensitivity is enabled, it is possible to use CreateFile to with case-sensitive paths. To do that, you have to pass the FILE_FLAG_POSIX_SEMANTICS as part of the dwFlagsAndAttributes parameter. From msdn:
Access will occur according to POSIX rules. This includes allowing multiple files with names, differing only in case, for file systems that support that naming.
I found this part in this answer.
By setting the registry setting and the CreateFile flag, I was able to access case-sensitive paths.

what does terminal command: ls -l show?

I know that it outputs the "long" version but what do each of the sections mean?
On my mac, when I type in
ls -l /Users
I get
total 0
drwxr-xr-x+ 33 MaxHarris staff 1122 Jul 1 14:06 MaxHarris
drwxrwxrwt 8 root wheel 272 May 20 13:26 Shared
drwxr-xr-x+ 14 admin staff 476 May 17 11:25 admin
drwxr-xr-x+ 44 hugger staff 1496 Mar 17 21:13 hugger
I know that the first line it the permissions, although I don't know what the order is. It would be great if that could be explained too. Then whats the number after it?
Basically, what do each one of these things mean? Why are the usernames written twice sometimes and don't match other times?
The option '-l' tells the command to use a long list format. It gives back several columns wich correspond to:
Permissions
Number of hardlinks
File owner
File group
File size
Modification time
Filename
The first letter in the permissions column show the file's type. A 'd' means a directory and a '-' means a normal file (there are other characters, but those are the basic ones).
The next nine characters are divided into 3 groups, each one a permission. Each letter in a group correspond to the read, write and execute permission, and each group correspond to the owner of the file, the group of the file and then for everyone else.
[ File type ][ Owner permissions ][ Group permissions ][ Everyone permissions ]
The characters can be one of four options:
r = read permission
w = write permission
x = execute permission
- = no permission
Finally, the "+" at the end means some extended permissions.
If you type the command
$ man ls
You’ll get the documentation for ls, which says in part:
The Long Format
If the -l option is given, the following information is displayed for
each file: file mode, number of links, owner name, group name, number of
bytes in the file, abbreviated month, day-of-month file was last modified, hour file last modified, minute file last modified, and the pathname. In addition, for each directory whose contents are displayed, the
total number of 512-byte blocks used by the files in the directory is
displayed on a line by itself, immediately before the information for the
files in the directory. If the file or directory has extended
attributes, the permissions field printed by the -l option is followed by
a '#' character. Otherwise, if the file or directory has extended security information (such as an access control list), the permissions field
printed by the -l option is followed by a '+' character.
…
The man command is short for “manual”, and the articles it shows are called “man pages”; try running man manpages to learn even more about them.
The following information is provided:
permissions
number of linked hardlinks
owner of the file
to which group this file belongs to
size
modification/creation date and time
file/directory name

Resources