OSX: detect 'restricted' filesystem flag programmatically - swift

Starting from El Capitan the system got System Integrity Protection which doesn't allow certain activities for some folders and files. Using Terminal "ls lO" command you can see flags that specific file or folder has.
drwxr-xr-x# 3 root wheel hidden 96 Aug 12 2014 opt
drwxr-xr-x 6 root wheel sunlnk,hidden 192 Nov 28 15:14 private
drwxr-xr-x# 64 root wheel restricted,hidden 2048 Nov 29 13:48 sbin
lrwxr-xr-x# 1 root wheel restricted,hidden 11 Nov 28 15:13 tmp -> private/tmp
drwxr-xr-x# 10 root wheel restricted,hidden 320 Nov 28 15:21 usr
lrwxr-xr-x# 1 root wheel restricted,hidden 11 Nov 28 15:13 var -> private/var
I'm interested in "restricted" flag. How can it be found using Swift without executing terminal commands?
I want to emphasize that executing Process() in code is not an approach that suits the needs.
"Hidden" flag can be detected via "isHidden" property from here URLResourceKey. However there is nothing about "restricted".
Could somebody point me to the right direction?

The things listed by the -O option on the ls tool are the file flags. These can be read by the stat() function in the BSD layer, and are found in the st_flags field of the resulting structure.
The "restricted" flag in ls's output corresponds to SF_RESTRICTED, so you can read it by doing something like this:
func isRestricted(at url: URL) throws -> Bool {
let flags: UInt32 = try url.withUnsafeFileSystemRepresentation { fsRep in
var info = stat()
if stat(fsRep, &info) != 0 {
guard let code = POSIXError.Code(rawValue: errno) else {
throw CocoaError(.fileReadUnknown)
}
throw POSIXError(code)
}
return info.st_flags
}
return flags & UInt32(bitPattern: SF_RESTRICTED) != 0
}

Related

Why logrotate doesn't properly postrotate only has 1 day delay

I have in /etc/logrotate.d/mikrotik :
/var/log/mikrotik.log {
rotate 2
daily
compress
dateext
dateyesterday
dateformat .%Y-%m-%d
postrotate
#/usr/sbin/invoke-rc.d syslog-ng reload >/dev/null
rsync -avH /var/log/mikrotik*.gz /backup/logs/mikrotik/
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
The mikrotik.log.YYYY-MM-DD.gz file is created daily
The problem is that rsync in postrotate doesn't copy the last file. For example, on September 25, 2021, there are such files in /var/log:
-rw-r ----- 1 root adm 37837 Sep 24 23:49 mikrotik.log. 2021-09-24.gz
-rw-r ----- 1 root adm 36980 Sep 25 23:55 mikrotik.log. 2021-09-25.gz
and in /backup/logs/mikrotik/ are only:
-rw-r ----- 1 root adm 35495 Sep 23 00:00 mikrotik.log. 2021-09-22.gz
-rw-r ----- 1 root adm 36842 Sep 23 23:58 mikrotik.log. 2021-09-23.gz
-rw-r ----- 1 root adm 37837 Sep 24 23:49 mikrotik.log. 2021-09-24.gz
There is no file mikrotik.log.2021-09-25.gz from Sep 25 23:55 it will not be copied until the next rotation.
How to make a file packed today copied by postrotate ?
Problem solved.
It relied on the order in which the operations were performed.
Lgrotate does a 'postrotate' section before compressing to .gz.
The solution to the problem was to change the name from 'postrotate' to 'lastaction'.

macOS, Swift: Find current user's Applications directory (not the global "/Applications" directory)

On macOS in Swift, how can I obtain the name of the current user's Applications directory?
In other words, NOT the global "/Applications" directory, but the one just for the current user, for example "/Users/eric/Applications" or perhaps "/Users/eric/Library/Containers/com.eric.MyApp/Data/Applications"
The following code:
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
let listOfSearchPathDirectory: [FileManager.SearchPathDirectory] = [
.applicationDirectory,
.allApplicationsDirectory
]
let listOfSearchPathDomainMask = [
FileManager.SearchPathDomainMask.userDomainMask
]
let fileManager = FileManager.default
for searchPathDirectory in listOfSearchPathDirectory {
print(" A [\(searchPathDirectory.rawValue)]")
for searchPathDomainMask in listOfSearchPathDomainMask {
for url in fileManager.urls(for: searchPathDirectory, in: searchPathDomainMask) {
print(" B [\(url)]")
}
}
}
}
}
generates output like this:
A [1]
B [file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Applications/]
A [100]
B [file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Applications/]
B [file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Applications/Utilities/]
B [file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Developer/Applications/]
B [file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Applications/Demos/]
which includes what I thought would be the correct value:
file:///Users/eric/Library/Containers/com.eric.MyApp/Data/Applications/
but when I run the application, that directory does not exist.
In fact if I list the contents of its parent directory by typing this in the Terminal application:
ls -l /Users/eric/Library/Containers/com.eric.MyApp/Data
I get the following, but this does NOT include the expected directory "Applications":
> lrwxr-xr-x 1 eric staff 19 22 Jun 11:37 Desktop -> ../../../../Desktop
> drwx------ 3 eric staff 96 22 Jun 11:37 Documents
> lrwxr-xr-x 1 eric staff 21 22 Jun 11:37 Downloads -> ../../../../Downloads
> drwx------ 30 eric staff 960 22 Jun 11:37 Library
> lrwxr-xr-x 1 eric staff 18 22 Jun 11:37 Movies -> ../../../../Movies
> lrwxr-xr-x 1 eric staff 17 22 Jun 11:37 Music -> ../../../../Music
> lrwxr-xr-x 1 eric staff 20 22 Jun 11:37 Pictures -> ../../../../Pictures
I was hoping to have also seen a line like this:
> lrwxr-xr-x 1 eric staff 19 22 Jun 11:37 Applications -> ../../../../Applications
Anyone know how I can tell the code that I want this local Applications directory to exist?
Many thanks
You get the directory with
do {
let userApplicationDirectory = try FileManager.default.url(for: .applicationDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
print(userApplicationDirectory)
} catch { print(error)}
If the directory is missing it will be created.
If the app is sandboxed it points to .../Data/Applications in the container, otherwise to ~/Applications

Perl touch -t file error for a future date

I am trying to touch a file(for referencing date) with a future date something like -
Current date - $date
Fri Jan 6 03:59:55 EST 2017
touch -t 201702032359.59 /var/tmp/ME_FILE_END
on checking the timestamp of the file as -
$ ls -lrt /var/tmp/ME_FILE_END
getting an output with only date and not the entire timestamp(hhmm.sec)
-rw-r--r-- 1 abcproc abc 0 Feb 3 2017 /var/tmp/ME_FILE_END
But for a date with is less than or equal to current it gives correct result -
touch -t 201612010000.00 /var/tmp/ME_FILE_START
ls -lrt /var/tmp/ME_FILE_START
-rw-r--r-- 1 abcproc abc 0 Dec 1 00:00 /var/tmp/ME_FILE_START
Can someone please suggest why this discrepancy ?
It's just the way ls displays the date. When far from now, the modification time is not displayed.
If you want details regarding the last access / modification / change time, you should be using stat.
stat /var/tmp/ME_FILE_END
You will see the expected output.
For example:
[10:29:41]dabi#gaia:~$ touch -t 201702032359.59 /var/tmp/ME_FILE_END
[10:29:43]dabi#gaia:~$ ls -ltr /var/tmp/ME_FILE_END
-rw-rw-r-- 1 dabi dabi 0 feb. 3 2017 /var/tmp/ME_FILE_END
[10:29:47]dabi#gaia:~$ stat /var/tmp/ME_FILE_END
File : '/var/tmp/ME_FILE_END'
Size : 0 Blocks : 0 I/O blocks : 4096 empty file
Device : 803h/2051d Inode : 5374373 Links : 1
Access : (0664/-rw-rw-r--) UID : ( 1000/ dabi) GID : ( 1000/ dabi)
Access : 2017-02-03 23:59:59.000000000 +0100
Change : 2017-02-03 23:59:59.000000000 +0100
Change : 2017-01-06 10:29:43.364630503 +0100
Birth : -

Touchscreen on Raspberry Pi emits click not touch

i folowed this link to calibrate touchscreen: http://www.circuitbasics.com/raspberry-pi-touchscreen-calibration-screen-rotation/.
ls -la /dev/input/
total 0
drwxr-xr-x 4 root root 240 Jul 12 18:38 .
drwxr-xr-x 15 root root 3460 Jul 12 18:38 ..
drwxr-xr-x 2 root root 140 Jul 12 18:38 by-id
drwxr-xr-x 2 root root 140 Jul 12 18:38 by-path
crw-rw---- 1 root input 13, 64 Jul 12 18:38 event0
crw-rw---- 1 root input 13, 65 Jul 12 18:38 event1
crw-rw---- 1 root input 13, 66 Jul 12 18:38 event2
crw-rw---- 1 root input 13, 67 Jul 12 18:38 event3
crw-rw---- 1 root input 13, 68 Jul 12 18:38 event4
crw-rw---- 1 root input 13, 63 Jul 12 18:38 mice
crw-rw---- 1 root input 13, 32 Jul 12 18:38 mouse0
crw-rw---- 1 root input 13, 33 Jul 12 18:38 mouse1
root#raspberrypi:/sys/devices/virtual/input# cat input4/uevent
PRODUCT=0/0/0/0
NAME="FT5406 memory based driver"
PROP=2
EV=b
KEY=400 0 0 0 0 0 0 0 0 0 0
ABS=2608000 3
MODALIAS=input:b0000v0000p0000e0000-e0,1,3,k14A,ra0,1,2F,35,36,39,mlsfw
root#raspberrypi:~# cat /etc/ts.conf
# Uncomment if you wish to use the linux input layer event interface
module_raw input
# Uncomment if you're using a Sharp Zaurus SL-5500/SL-5000d
# module_raw collie
# Uncomment if you're using a Sharp Zaurus SL-C700/C750/C760/C860
# module_raw corgi
# Uncomment if you're using a device with a UCB1200/1300/1400 TS interface
# module_raw ucb1x00
# Uncomment if you're using an HP iPaq h3600 or similar
# module_raw h3600
# Uncomment if you're using a Hitachi Webpad
# module_raw mk712
# Uncomment if you're using an IBM Arctic II
# module_raw arctic2
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear
I only get response when configuring X with xinput_calibrator. When i enter this command
sudo TSLIB_FBDEVICE=/dev/fb0 TSLIB_TSDEVICE=/dev/input/event1 ts_calibrate
I get optput
xres = 800, yres = 480
selected device is not a touchscreen I understand
Can someone please help me,
Thanks in advance.
I don't have a solution for this, but I believe that it is related to the problem of touches being treated as mouseovers. This bug has been reported several times, but never actually fixed
https://gitlab.gnome.org/GNOME/gtk/-/issues/945
https://bugzilla.gnome.org/show_bug.cgi?id=789041
https://bugs.launchpad.net/ubuntu-mate/+bug/1792787
A bugzilla.gnome.org user named niteshgupta16 created a script that solves this problem, but it was uploaded to pasting/sharing service called hastebin at https://www.hastebin.com/uwuviteyeb.py.
Hastebin deletes files that have not been accessed within 30 days. Since hastebin is a javascript-obfuscated service, this file is not available on archive.org.
I am unable to find an email for niteshgupta16 in order to ask him if he still has uwuviteyeb.py.

Executing shell commands from Scala REPL

An interesting feature of Scala REPL is if you drop any jar in your %SCALA_HOME%\lib directory, it is available for import from the REPL. I have several jars there, and I often need to find out which ones are available to be included. So I always have to open another command window and find out which jars exist in that directory. It would be great if the REPL allowed me to execute system commands such as dir or ls or at least list all the jars in the above lib directory. What is the easiest way (if any) to invoke shell commands in REPL ?
In REPL the :sh command allow you to introduce shell command:
Windows version:
scala> :sh cmd /C dir
res0: scala.tools.nsc.interpreter.ProcessResult = `cmd /C dir` (28 lines, exit 0)
scala> res0 foreach println
(unfortunately, there is no way to avoid the call to cmd \C before the shell command)
Unix-like version:
scala> :sh ls
res0: scala.tools.nsc.interpreter.ProcessResult = `cmd /C dir` (28 lines, exit 0)
scala> res0 foreach println
Update: Inspired by Daniel's answer, a little trick for windows user:
scala> implicit def stringToDosProcess(s: String) =
scala.sys.process.stringToProcess("cmd /C "+ s)
stringToDosProcess: (s: String)scala.sys.process.ProcessBuilder
scala> "dir".!
Alternative: use Scala's sys.process library:
scala> import sys.process._
import sys.process._
scala> "ls /home/dcs/scala-2.9.1.final".!
bin
doc
lib
man
meta
misc
src
res1: Int = 0
UPDATE
The means for extracting :sh output has changed over the years.
Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_91).
Type in expressions for evaluation. Or try :help.
scala> :sh date
res0: scala.tools.nsc.interpreter.ProcessResult = `date` (1 lines, exit 0)
scala> res0 foreach println
<console>:13: error: value foreach is not a member of scala.tools.nsc.interpreter.ProcessResult
res0 foreach println
^
scala> res0.show
<console>:13: error: value show is not a member of scala.tools.nsc.interpreter.ProcessResult
res0.show
^
scala> res0.lines
res3: List[String] = List(Sat Sep 17 19:29:26 PDT 2016)
Here is a little-known trick of REPL:
Welcome to Scala version 2.10.0-20120323-101508-45eebcf98d (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).
Type in expressions to have them evaluated.
Type :help for more information.
scala> /home/dcs/scala-2.9.1.final/<TAB>
/home/dcs/scala-2.9.1.final/misc /home/dcs/scala-2.9.1.final/bin /home/dcs/scala-2.9.1.final/man /home/dcs/scala-2.9.1.final/src /home/dcs/scala-2.9.1.final/lib
/home/dcs/scala-2.9.1.final/meta /home/dcs/scala-2.9.1.final/doc
scala> /home/dcs/scala-2.9.1.final/lib/<TAB>
/home/dcs/scala-2.9.1.final/lib/scala-dbc.jar /home/dcs/scala-2.9.1.final/lib/scala-swing.jar /home/dcs/scala-2.9.1.final/lib/jline.jar
/home/dcs/scala-2.9.1.final/lib/scala-library.jar /home/dcs/scala-2.9.1.final/lib/scala-compiler.jar /home/dcs/scala-2.9.1.final/lib/scalap.jar
scala> /home/dcs/scala-2.9.1.final/lib/scala-library.jar
res0: scala.tools.nsc.io.File = /home/dcs/scala-2.9.1.final/lib/scala-library.jar
Where <TAB> is I pressing tab.
UPDATE 2018/01/15
Example: you like to see the files in the current working directory:
scala> :sh ls -l
res3: scala.tools.nsc.interpreter.ProcessResult = `ls -l` (13 lines, exit 0)
But you can't do this:
scala> res3.foreach {println}
<console>:40: error: value foreach is not a member of scala.tools.nsc.interpreter.ProcessResult
res3.foreach {println}
^
First you have to assign the lines to another type that supports iteration:
scala> res3.lines
res7: List[String] = List(total 960, -rw-r--r--# 1 dave staff 11325 Jan 3 15:01 LICENSE, -rw-r--r--# 1 dave staff 8859 Jan 3 15:01 README.rst, drwxr-xr-x# 3 dave staff 96 Jan 3 15:03 assembly, drwxr-xr-x# 20 dave staff 640 Jan 3 15:01 bin, drwxr-xr-x# 13 dave staff 416 Jan 3 15:01 doc, drwxr-xr-x# 7 dave staff 224 Jan 3 15:01 docker, drwxr-xr-x# 6 dave staff 192 Jan 3 15:03 examples, -rw-r--r--# 1 dave staff 826 Jan 3 15:01 gradle.properties, -rw-r--r--# 1 dave staff 128 Jan 3 15:04 h2o_drivers.txt, drwxr-xr-x 3 dave staff 96 Jan 16 00:54 h2ologs, drwxr-xr-x# 5 dave staff 160 Jan 3 15:04 py, -rw-r--r--# 1 dave staff 455890 Sep 19 04:18 rsparkling.tar.gz)
Then iterate, and voila!
scala> res7.foreach {println}
total 960
-rw-r--r--# 1 dave staff 11325 Jan 3 15:01 LICENSE
-rw-r--r--# 1 dave staff 8859 Jan 3 15:01 README.rst
drwxr-xr-x# 3 dave staff 96 Jan 3 15:03 assembly
drwxr-xr-x# 20 dave staff 640 Jan 3 15:01 bin
drwxr-xr-x# 13 dave staff 416 Jan 3 15:01 doc
drwxr-xr-x# 7 dave staff 224 Jan 3 15:01 docker
drwxr-xr-x# 6 dave staff 192 Jan 3 15:03 examples
-rw-r--r--# 1 dave staff 826 Jan 3 15:01 gradle.properties
-rw-r--r--# 1 dave staff 128 Jan 3 15:04 h2o_drivers.txt
drwxr-xr-x 3 dave staff 96 Jan 16 00:54 h2ologs
drwxr-xr-x# 5 dave staff 160 Jan 3 15:04 py
-rw-r--r--# 1 dave staff 455890 Sep 19 04:18 rsparkling.tar.gz