Commit f2edfd50 authored by Camil Staps's avatar Camil Staps 🚀

Also pass event->name through; inotify_loop_forever

parent 5eb4267e
# Executables
*.exe
*.out
test
# Directory used to store object files, abc files and assembly files
Clean System Files/
......@@ -9,3 +8,6 @@ Clean System Files/
# iTasks environment extra data
*-data/
sapl/
test
test_reload
......@@ -9,7 +9,7 @@ from Data.Maybe import ::Maybe
:: INMask :== Int
:: INEvent :== Int
:: INCallback st :== INEvent st *World -> *(st, *World)
:: INCallback st :== INEvent (Maybe String) st *World -> *(st, *World)
(|-) infixl 6 :: (INMask INMask -> INMask)
......@@ -23,6 +23,8 @@ inotify_rm_watch :: !INWatch !*(Inotify st) -> *(Bool, *Inotify st)
inotify_poll :: *(Inotify st) -> *Inotify st
inotify_check :: *(Inotify st) *World -> *(*Inotify st, *World)
inotify_loop_forever :: *(Inotify st) *World -> *(*Inotify st, *World)
IN_ACCESS :== 0x00000001 // File was accessed
IN_MODIFY :== 0x00000002 // File was modified
IN_ATTRIB :== 0x00000004 // Metadata changed
......
implementation module Inotify
import Data.Either
import Data.List
import Data.Maybe
import StdArray
......@@ -74,22 +75,25 @@ where
inotify_check :: *(Inotify st) *World -> *(*Inotify st, *World)
inotify_check inot=:{fd,watches,state} w
# (ok, wds, masks, fd) = c_check fd
# (ok, wds, masks, fnames, fd) = c_check fd
inot = { inot & fd=fd }
| not ok = (inot, w)
| (size wds) rem 4 <> 0 || (size masks) rem 4 <> 0 = (inot,w)
# (wds,masks) = (split 4 wds, split 4 masks)
# (wds,masks,fnames) = (split 4 wds, split 4 masks, splitOn '\0' fnames)
| length wds <> length masks = (inot, w)
# wdsmasks = zip2 (map bytesToInt wds) (map bytesToInt masks)
# (fd,st,w`) = seq (map (check wdsmasks) watches) (inot.fd, state, w)
# infos = zip3 (map bytesToInt wds) (map bytesToInt masks) fnames
# (fd,st,w`) = seq (map (check infos) watches) (inot.fd, state, w)
= ({ inot & fd=fd, state=st }, w`)
where
check :: [(Int,Int)] (INWatch, INCallback st) *(*Int, st, *World)
check :: [(Int,Int,String)] (INWatch, INCallback st) *(*Int, st, *World)
-> *(*Int, st, *World)
check wdsmasks (watch,f) (fd,st,w)
# (st,w) = seq [\(st,w) -> f mask st w
\\ (wd,mask) <- wdsmasks | wd == watch] (st,w)
check infos (watch,f) (fd,st,w)
# (st,w) = seq [\(st,w) -> f mask (toMaybe name) st w
\\ (wd,mask,name) <- infos | wd == watch] (st,w)
= (fd,st,w)
where
toMaybe :: String -> Maybe String
toMaybe s = if (s=="") Nothing (Just s)
bytesToInt :: {#Char} -> Int
bytesToInt cs = sum [toInt c * (8 ^ p) \\ c <-: cs & p <- [0..]]
......@@ -99,12 +103,26 @@ where
| size s > n = [s % (0,n-1) : split n (s % (n, size s - 1))]
| size s == n = [s]
| s == "" = []
splitOn :: Char String -> [String]
splitOn c s = map toString (split` c [c \\ c <-: s])
where
split` :: Char [Char] -> [[Char]]
split` c [] = []
split` c cs=:[x:xs]
= let (l,r) = span ((<>)c) cs in [l:split` c (removeMember c r)]
c_check :: !*Int -> *(!Bool, !String, !String, !*Int)
c_check :: !*Int -> *(!Bool, !String, !String, !String, !*Int)
c_check fd = code {
ccall clean_inotify_check "I:VISSI"
ccall clean_inotify_check "I:VISSSI"
}
inotify_loop_forever :: *(Inotify st) *World -> *(*Inotify st, *World)
inotify_loop_forever inot w
# inot = inotify_poll inot
# (inot,w) = inotify_check inot w
= inotify_loop_forever inot w
errno :: Int
errno = err 0
where
......
......@@ -11,9 +11,15 @@ $(INO_OBJ): inotify_c.c
test: test.icl $(wildcard *.*cl) $(INO_OBJ)
$(CPM) project $@.prj build
test_reload: test_reload.icl $(wildcard *.*cl) $(INO_OBJ)
$(CPM) project $@.prj build
run_test: test
./test
run_test_reload: test_reload
while :; do ./test_reload; done
clean:
rm -rfv Clean\ System\ Files
......
......@@ -54,9 +54,11 @@ void clean_poll(int fd, int *re_nrevents, int *re_fd) {
static CleanStringVariable(wds_string, 1024);
static CleanStringVariable(masks_string, 1024);
static CleanStringVariable(names_string, 4096);
void clean_inotify_check(int fd,
int *re_ok, CleanString* re_wds, CleanString* re_masks, int *re_fd) {
int *re_ok, CleanString* re_wds, CleanString* re_masks,
CleanString* re_fnames, int *re_fd) {
char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *ev;
ssize_t len;
......@@ -67,17 +69,20 @@ void clean_inotify_check(int fd,
char *wds_ptr = CleanStringCharacters(wds_string);
char *masks_ptr = CleanStringCharacters(masks_string);
char *names_ptr = CleanStringCharacters(names_string);
CleanStringLength(wds_string) = 0;
CleanStringLength(masks_string) = 0;
CleanStringLength(names_string) = 0;
*re_ok = 0;
*re_fd = fd;
*re_wds = (CleanString) &empty_string;
*re_masks = (CleanString) &empty_string;
*re_fnames = (CleanString) &empty_string;
for (;;) {
poll_n = poll(&pfd, 1, 50);
poll_n = poll(&pfd, 1, 0);
if (poll_n < 0) {
return;
} else if (poll_n == 0) {
......@@ -103,11 +108,18 @@ void clean_inotify_check(int fd,
memcpy(wds_ptr, &ev->wd, sizeof(int));
wds_ptr += sizeof(int);
CleanStringLength(wds_string) += sizeof(int);
int len = strlen(ev->name);
memcpy(names_ptr, &ev->name, len);
names_ptr += len + 1;
*(names_ptr - 1) = '\00';
CleanStringLength(names_string) += len + 1;
}
}
*re_wds = (CleanString) wds_string;
*re_masks = (CleanString) masks_string;
*re_fnames = (CleanString) names_string;
*re_ok = 1;
}
......@@ -11,21 +11,20 @@ Start w
= inotify_add_watch (echo "file1") IN_ALL_EVENTS "file1" inot
# (Right watch, inot)
= inotify_add_watch (echo "file2") IN_ALL_EVENTS "file2" inot
# (io,w) = stdio w
# io = io <<< "Do something with file1 or file2\n"
# (ok,w) = fclose io w
# (inot, w) = loop inot w
# (io,w) = stdio w
# io = io <<< "Do something with file1 or file2\n"
# (ok,w) = fclose io w
# (inot, w) = inotify_loop_forever inot w
= inotify_close inot
where
loop :: !*(Inotify st) !*World -> *(*Inotify st, *World)
loop inot w
# inot = inotify_poll inot
# (inot, w) = inotify_check inot w
= loop inot w
echo :: String INEvent Int *World -> *(Int, *World)
echo fname ev i w
# (io,w) = stdio w
# io = io <<< "EVENT: [" <<< fname <<< "; " <<< ev <<< "]\n"
# (ok,w) = fclose io w
echo :: String INEvent (Maybe String) Int *World -> *(Int, *World)
echo fname ev f i w
# (io,w) = stdio w
# io = io <<< "EVENT: ["<<< fname <<<"; "<<< ev <<<"; "<<< f <<<"]\n"
# (ok,w) = fclose io w
= (i, w)
instance <<< (Maybe a) | <<< a
where
(<<<) f Nothing = f
(<<<) f (Just x) = f <<< x
module test_reload
import StdBool
import StdClass
import StdFile
import StdFunc
import StdInt
import StdString
import Data.Either
import Data.Maybe
import Inotify
/** test_reload
*
* This module will watch the directory it is in. Whenever the attributes of
* its own binaries change, it will exit. Hence, putting it in a loop:
*
* while :; do ./test_reload; done
*
* will give a program that automatically reloads itself when its binary has
* changed.
*
* Test it by running `make run_test_reload`, then editing `changeme` below and
* running `make test_reload` to recompile.
*/
my_name :== "test_reload"
my_dir :== "."
changeme :== 42
verbose :== False
:: Void = Void
Start w
# (io,w) = stdio w
# io = io <<< changeme <<< "\n"
# (ok,w) = fclose io w
# (Just inot) = inotify_init Void
# (Right watch,inot) = inotify_add_watch reload IN_ALL_EVENTS my_dir inot
# (inot,w) = inotify_loop_forever inot w
= inotify_close inot
where
reload :: !INEvent (Maybe String) Void !*World -> *(Void, *World)
reload ev mbName _ w
# w = echo (\f -> f <<< "event: " <<< ev <<< "; " <<< mbName) w
| isNothing mbName = (Void, w)
# (Just name) = mbName
| ev bitand IN_ATTRIB <> 0 && name == my_name
# w = echo (\f -> f <<< "reloading...") w
# w = exit 127 w
= (Void, w)
= (Void, w)
echo :: (*File -> *File) *World -> *World
echo f w
# (io,w) = stdio w
# io = if verbose (flip (<<<) "\n" o f) id io
# (ok,w) = fclose io w
= w
exit :: !Int !*World -> *World
exit c w = code {
ccall exit "I:V:A"
}
instance <<< (Maybe x) | <<< x
where
(<<<) f Nothing = f
(<<<) f (Just x) = f <<< x
Version: 1.4
Global
ProjectRoot: .
Target: StdEnv
Exec: {Project}/test_reload
CodeGen
CheckStacks: False
CheckIndexes: True
Application
HeapSize: 2097152
StackSize: 512000
ExtraMemory: 8192
IntialHeapSize: 204800
HeapSizeMultiplier: 4096
ShowExecutionTime: False
ShowGC: False
ShowStackSize: False
MarkingCollector: False
DisableRTSFlags: False
StandardRuntimeEnv: True
Profile
Memory: False
MemoryMinimumHeapSize: 0
Time: False
Stack: False
Output
Output: ShowConstructors
Font: Monaco
FontSize: 9
WriteStdErr: False
Link
LinkMethod: Static
GenerateRelocations: False
GenerateSymbolTable: False
GenerateLinkMap: False
LinkResources: False
ResourceSource:
GenerateDLL: False
ExportedNames:
Paths
Path: {Project}
Path: {Application}/lib/clean-platform/OS-Independent
Path: {Application}/lib/Generics
Precompile:
Postlink:
MainModule
Name: test_reload
Dir: {Project}
Compiler
NeverMemoryProfile: False
NeverTimeProfile: False
StrictnessAnalysis: True
ListTypes: StrictExportTypes
ListAttributes: True
Warnings: True
Verbose: True
ReadableABC: False
ReuseUniqueNodes: True
Fusion: False
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment