fileset

git mirror of https://ccx.te2000.cz/bzr/fileset
git clone https://ccx.te2000.cz/git/fileset
Log | Files | Refs | README

confz_fileset_init (7016B)


      1 # vim: ft=zsh noet ts=4 sts=4 sw=4
      2 
      3 #
      4 # confz functions for file hierarchies and fileset miniformat
      5 #
      6 
      7 zmodload -F zsh/stat b:zstat
      8 zmodload -m -F zsh/files b:zf_\*
      9 
     10 typeset -g -A fileset_stat_cache fileset_stat_cur fileset_ftypes fileset_typenames
     11 typeset -g fileset_stat_cur fileset_stat_next_id fileset_stat_cur_type fileset_stat_cur_perm fileset_stat_cur_major fileset_stat_cur_minor
     12 
     13 fileset_ftypes=(  # convert hex type to a word
     14 	C  S  # unix socket
     15 	c  S
     16 	A  L  # symlink, could also be 'h'
     17 	a  L
     18 	8  f  # plain file
     19 	6  b  # block device file
     20 	4  d  # directory
     21 	2  c  # character device file
     22 	1  p  # FIFO pipe
     23 )
     24 
     25 fileset_typenames=(
     26 	S "unix socket"
     27 	L "symbolic link"
     28 	f "plain file"
     29 	b "block device"
     30 	c "character device"
     31 	p "named pipe"
     32 )
     33 
     34 fileset_reset_cache(){
     35 	# omit unsetting used variables for now
     36 	# probably no particular gain in freeing them
     37 	fileset_stat_cache=()
     38 	fileset_stat_cur=()
     39 	fileset_stat_next_id=1
     40 }
     41 fileset_reset_cache
     42 
     43 # runs zstat on $1 if not already in cache
     44 # the result is available as $fileset_stat_cur associative array
     45 fileset_stat() {
     46 	local id ret ftype fperm
     47 	id=${fileset_stat_cache[$1]:-missing}
     48 	if [[ $id == missing ]]; then
     49 		typeset -gA fileset_stat_$fileset_stat_next_id 
     50 		zstat -L -H fileset_stat_$fileset_stat_next_id $1 &>/dev/null
     51 		ret=$?
     52 		if (($ret == 0)); then
     53 			fileset_stat_cache[$1]=$fileset_stat_next_id
     54 			fileset_stat_set_cur $fileset_stat_next_id
     55 			fileset_stat_next_id=$[ $fileset_stat_next_id + 1 ]
     56 		else
     57 			fileset_stat_cache[$1]=-$ret
     58 		fi
     59 		return $ret
     60 	elif (( $id >= 0 )); then
     61 		fileset_stat_set_cur $id
     62 		return 0
     63 	else
     64 		return $[ -($id) ]
     65 	fi
     66 }
     67 
     68 fileset_stat_set_cur(){
     69 	local param ftype
     70 	param=fileset_stat_$1
     71 	fileset_stat_cur=( "${(@kvP)param}" )
     72 	ftype=$[ [##16] $fileset_stat_cur[mode] >> 12 ]
     73 	fileset_stat_cur_type=$fileset_ftypes[$ftype]
     74 	fileset_stat_cur_perm=$[ [##8] $fileset_stat_cur[mode] & 4095 ]
     75 	fileset_stat_cur_major=$[ $fileset_stat_cur[rdev] >> 8 ]
     76 	fileset_stat_cur_minor=$[ $fileset_stat_cur[rdev] & 255 ]
     77 }
     78 
     79 fileset_resetcmd() {
     80 	fileset_reset_cache
     81 	"$@"
     82 }
     83 
     84 confz_fs_p_check() {
     85 	checkvars filename
     86 	local parent
     87 	parent=${${vars[filename]}:h}
     88 	do_command=( fileset_resetcmd mkdir -p $parent )
     89 	fileset_stat $parent && [[ $fileset_stat_cur_type == d ]]
     90 }
     91 
     92 
     93 confz_fs_type_or_missing_check() {
     94 	checkvars filename flags filetype
     95 	if fileset_stat $vars[filename]; then
     96 		if [[ $fileset_stat_cur_type == $vars[filetype] ]]; then
     97 			return 0
     98 		elif [[ $vars[flags] == *'!'* ]]; then
     99 			fail_reason="expected ${fileset_typenames[${vars[filetype]}]}, got ${fileset_typenames[$fileset_stat_cur_type]}: ${(qqq)vars[filename]}"
    100 			return 1
    101 		else
    102 			die "$0: expected ${fileset_typenames[${vars[filetype]}]}, got ${fileset_typenames[$fileset_stat_cur_type]}: ${(qqq)vars[filename]}"
    103 		fi
    104 	else
    105 		return 0
    106 	fi
    107 }
    108 
    109 confz_fs_type_or_missing_do() {
    110 	local is_dir
    111 	if fileset_stat $vars[filename] && [[ $fileset_stat_cur_type == d ]]; then
    112 		is_dir=1
    113 	else
    114 		is_dir=0
    115 	fi
    116 
    117 	fileset_reset_cache
    118 	if [[ $vars[flags] == *r* ]]; then
    119 		if [[ $vars[flags] == *f* ]]; then
    120 			zf_rm -rf $vars[filename]
    121 		else
    122 			zf_rm -r $vars[filename]
    123 		fi
    124 	elif (($is_dir)); then
    125 		zf_rmdir $vars[filename]
    126 	else
    127 		if [[ $vars[flags] == *f* ]]; then
    128 			zf_rm -f $vars[filename]
    129 		else
    130 			zf_rm $vars[filename]
    131 		fi
    132 	fi
    133 }
    134 
    135 
    136 confz_fs_l_check() {
    137 	checkvars filename destination
    138 	defvar flags ''
    139 
    140 	if [[ $vars[flags] == *p* ]]; then
    141 		require fs_p :filename
    142 	fi
    143 
    144 	require fs_type_or_missing :filename :flags filetype=L
    145 
    146 	fileset_stat $vars[filename] && \
    147 		[[ $fileset_stat_cur_type == L ]] && \
    148 		[[ $fileset_stat_cur[link] == $vars[destination] ]]
    149 }
    150 
    151 confz_fs_l_do() {
    152 	local missing
    153 	fileset_stat $vars[filename]
    154 	missing=$?
    155 	fileset_reset_cache
    156 	if ! (($missing)); then
    157 		rm $vars[filename] || return $?
    158 	fi
    159 	zf_ln -sh $vars[destination] $vars[filename]
    160 }
    161 
    162 
    163 confz_fs_device_check() {
    164 	checkvars filename device_type major minor
    165 	defvar flags ''
    166 
    167 	if [[ $vars[flags] == *p* ]]; then
    168 		require fs_p :filename
    169 	fi
    170 
    171 	case $vars[device_type] in
    172 		(c) require fs_type_or_missing :filename :flags filetype=c ;;
    173 		(b) require fs_type_or_missing :filename :flags filetype=b ;;
    174 		(*) die "Incorrect device type: ${(qqq)vars[device_type]}" ;;
    175 	esac
    176 
    177 	fileset_stat $vars[filename] && \
    178 		[[ $fileset_stat_cur_type == $vars[device_type] ]] && \
    179 		[[ $fileset_stat_cur_major == $vars[major] ]] && \
    180 		[[ $fileset_stat_cur_minor == $vars[minor] ]]
    181 }
    182 
    183 confz_fs_device_do() {
    184 	local missing
    185 	fileset_stat $vars[filename]
    186 	missing=$?
    187 	fileset_reset_cache
    188 	if ! (($missing)); then
    189 		rm $vars[filename] || return $?
    190 	fi
    191 	mknod $vars[filename] $vars[device_type] $vars[major] $vars[minor]
    192 }
    193 
    194 
    195 confz_fs_pipe_check() {
    196 	checkvars filename
    197 	defvar flags ''
    198 
    199 	if [[ $vars[flags] == *p* ]]; then
    200 		require fs_p :filename
    201 	fi
    202 
    203 	require fs_type_or_missing :filename :flags filetype=p
    204 
    205 	do_command=( fileset_resetcmd mkfifo $vars[filename] )
    206 	fileset_stat $vars[filename] && [[ $fileset_stat_cur_type == p ]]
    207 }
    208 
    209 
    210 confz_fs_r_check() {
    211 	checkvars filename
    212 	defvar flags ''
    213 	do_command=( confz_fs_type_or_missing_do )
    214 	! fileset_stat $vars[filename]
    215 }
    216 
    217 
    218 confz_fs_m_check() {
    219 	checkvars filename mode
    220 	do_command=( fileset_resetcmd chmod $vars[mode] $vars[filename] )
    221 	fileset_stat $vars[filename] && (( $fileset_stat_cur_perm == $vars[mode] ))
    222 }
    223 
    224 
    225 confz_fs_o_check() {
    226 	checkvars filename owner
    227 	do_command=( fileset_resetcmd zf_chown -h $vars[owner] $vars[filename] )
    228 	fileset_stat $vars[filename] || \
    229 		die "fs_o: could not access file ${(qqq)vars[filename]}"
    230 
    231 	if [[ $vars[owner] =~ '^[0-9]+:[0-9]+$' ]]; then
    232 		(( $fileset_stat_cur[uid] == ${${vars[owner]}%:*} && \
    233 			$fileset_stat_cur[gid] == ${${vars[owner]}#*:} ))
    234 	elif [[ $vars[owner] =~ '^[0-9]+$' ]]; then
    235 		(( $fileset_stat_cur[uid] == ${${vars[owner]}%:*} ))
    236 	else
    237 		die "fs_o does not support non-numeric user/group: ${(qqq)vars[owner]}"
    238 	fi
    239 }
    240 
    241 
    242 confz_fs_f_check() {
    243 	checkvars filename
    244 	defvar flags ''
    245 
    246 	if [[ $vars[flags] == *p* ]]; then
    247 		require fs_p :filename
    248 	fi
    249 
    250 	require fs_type_or_missing :filename :flags filetype=f
    251 
    252 	fileset_stat $vars[filename] && [[ $fileset_stat_cur_type == f ]]
    253 }
    254 
    255 confz_fs_f_do() {
    256 	fileset_reset_cache
    257 	printf '' >> $vars[filename]
    258 }
    259 
    260 
    261 confz_fs_d_check() {
    262 	checkvars filename
    263 	defvar flags ''
    264 
    265 	require fs_type_or_missing :filename :flags filetype=d
    266 
    267 	if [[ $vars[flags] == *p* ]]; then
    268 		do_command=( fileset_resetcmd mkdir -p $vars[filename] )
    269 	else
    270 		do_command=( fileset_resetcmd mkdir $vars[filename] )
    271 	fi
    272 
    273 	fileset_stat $vars[filename] && [[ $fileset_stat_cur_type == d ]]
    274 }
    275 
    276 
    277 confz_fs_c_check() {
    278 	checkvars filename content_call
    279 	defvar flags ''
    280 	require fs_f :filename :flags
    281 	"${(Q@)${(z)vars[content_call]}}" | cmp -s - $vars[filename]
    282 }
    283 
    284 confz_fs_c_do() {
    285 	"${(Q@)${(z)vars[content_call]}}" > $vars[filename]
    286 }
    287 
    288 confz_fs_contentnl_check() {
    289 	checkvars filename content
    290 	defvar flags ''
    291 	require fs_f :filename :flags
    292 	printf '%s\n' "$vars[content]" | cmp -s - $vars[filename]
    293 }
    294 confz_fs_contentnl_do() {
    295 	printf '%s\n' "$vars[content]" > $vars[filename]
    296 }
    297