#!/bin/sh # this script assumes anything on the disk can be removed if corrupted # other use cases may need different scripts. # currently only supports ext4 but should be expanded proc do_fsck { # preen /sbin/e2fsck -p $ifsjoin(Argv) global EXIT_CODE := $Status # exit code 1 is errors corrected test $(EXIT_CODE) -eq 1 && global EXIT_CODE := '0' # exit code 2 or 3 means need to reboot test $(EXIT_CODE) -eq 2 -o $(EXIT_CODE) -eq 3 && /sbin/reboot # exit code 4 or over is fatal test $(EXIT_CODE) -lt 4 && return "${EXIT_CODE}" # try harder /sbin/e2fsck -y $ifsjoin(Argv) # exit code 1 is errors corrected test $(EXIT_CODE) -eq 1 && global EXIT_CODE := '0' # exit code 2 or 3 means need to reboot test $(EXIT_CODE) -eq 2 -o $(EXIT_CODE) -eq 3 && /sbin/reboot # exit code 4 or over is fatal test $(EXIT_CODE) -ge 4 && printf "Filesystem unrecoverably corrupted, will reformat\n" return "${EXIT_CODE}" } proc do_fsck_extend_mount { global DRIVE := $1 global DATA := $2 do_fsck $DATA || return 1 # only try to extend if there is a single partition and free space global PARTITIONS := $[sfdisk -J $DRIVE | jq '.partitiontable.partitions | length] if test $PARTITIONS -eq 1 && \ sfdisk -F $DRIVE | grep -q 'Unpartitioned space' && ! sfdisk -F $DRIVE | grep -q '0 B, 0 bytes, 0 sectors' { global SPACE := $[sfdisk -F $DRIVE | grep 'Unpartitioned space] printf "Resizing disk partition: $SPACE\n" # 83 is Linux partition id global START := $[sfdisk -J $DRIVE | jq -e '.partitiontable.partitions | map(select(.type=="83")) | .[0].start] sfdisk -q --delete $DRIVE !2 > /dev/null echo "$(START),,83;" | sfdisk -q $DRIVE # set bootable flag sfdisk -A $DRIVE 1 # update status blockdev --rereadpt $diskdev !2 > /dev/null mdev -s # wait for device for i in [$[seq 1 50]] { test -b $DATA && break || sleep .1; mdev -s; } # resize2fs fails unless we use -f here do_fsck -f $DATA || return 1 resize2fs $DATA do_fsck $DATA || return 1 } } proc do_mkfs { global diskdev := $1 # new disks does not have an DOS signature in sector 0 # this makes sfdisk complain. We can workaround this by letting # fdisk create that DOS signature, by just do a "w", a write. # http://bugs.alpinelinux.org/issues/145 echo "w" | fdisk $diskdev >/dev/null # format one large partition echo ";" | sfdisk --quiet $diskdev # update status blockdev --rereadpt $diskdev !2 > /dev/null # wait for device for i in [$[seq 1 50]] { test -b $DATA && break || sleep .1; mdev -s; } global FSOPTS := '"-O resize_inode,has_journal,extent,huge_file,flex_bg,uninit_bg,64bit,dir_nlink,extra_isize'" mkfs.ext4 -q -F $FSOPTS $(diskdev)1 } # TODO fix for multiple disks, cdroms etc global DEV := $[find /dev -maxdepth 1 -type b ! -name 'loop*' | grep -v '[0-9]$' | sed 's@.*/dev/@@' | sort | head -1] test -z $(DEV) && exit 1 global DRIVE := ""/dev/$(DEV)"" # see if it has a partition table already if sfdisk -d $(DRIVE) >/dev/null !2 >/dev/null { global DATA := $[sfdisk -J $DRIVE | jq -e -r '.partitiontable.partitions | map(select(.type=="83")) | .[0].node] if test $Status -eq 0 { do_fsck_extend_mount $DRIVE $DATA || do_mkfs $DRIVE } else { do_mkfs $DRIVE } } else { do_mkfs $DRIVE } (CommandList children: [ (FuncDef name: do_fsck body: (BraceGroup children: [ (C {(/sbin/e2fsck)} {(-p)} {($ VSub_Star "$*")}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:EXIT_CODE) op: Equal rhs: {($ VSub_QMark "$?")} spids: [33] ) ] spids: [33] ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(1)} {(Lit_Other "]")}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:EXIT_CODE) op:Equal rhs:{(0)} spids:[57])] spids: [57] ) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(2)} {(-o)} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(3)} {(Lit_Other "]")} ) (C {(/sbin/reboot)}) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-lt)} {(4)} {(Lit_Other "]")}) (ControlFlow token: arg_word: {(DQ (${ VSub_Name EXIT_CODE))} ) ] op_id: Op_DAmp ) (C {(/sbin/e2fsck)} {(-y)} {($ VSub_Star "$*")}) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(1)} {(Lit_Other "]")}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:EXIT_CODE) op:Equal rhs:{(0)} spids:[157])] spids: [157] ) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(2)} {(-o)} {(DQ (${ VSub_Name EXIT_CODE))} {(-eq)} {(3)} {(Lit_Other "]")} ) (C {(/sbin/reboot)}) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name EXIT_CODE))} {(-ge)} {(4)} {(Lit_Other "]")}) (C {(printf)} { (DQ ("Filesystem unrecoverably corrupted, will reformat") (EscapedLiteralPart token:) ) } ) ] op_id: Op_DAmp ) (ControlFlow token: arg_word: {(DQ (${ VSub_Name EXIT_CODE))} ) ] spids: [19] ) spids: [15 18] ) (FuncDef name: do_fsck_extend_mount body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DRIVE) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [243] ) ] spids: [243] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DATA) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [249] ) ] spids: [249] ) (AndOr children: [ (C {(do_fsck)} {(DQ ($ VSub_Name "$DATA"))}) (ControlFlow token: arg_word:{(1)}) ] op_id: Op_DPipe ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:PARTITIONS) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(sfdisk)} {(-J)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(jq)} {(SQ <".partitiontable.partitions | length">)}) ] negated: False ) ] ) left_token: spids: [275 291] ) } spids: [274] ) ] spids: [274] ) (If arms: [ (if_arm cond: [ (AndOr children: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$PARTITIONS"))} {(-eq)} {(1)} {(Lit_Other "]")} ) (AndOr children: [ (Pipeline children: [ (C {(sfdisk)} {(-F)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(grep)} {(-q)} {(SQ <"Unpartitioned space">)}) ] negated: False ) (Pipeline children: [ (C {(sfdisk)} {(-F)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(grep)} {(-q)} {(SQ <"0 B, 0 bytes, 0 sectors">)}) ] negated: True ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:SPACE) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(sfdisk)} {(-F)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(grep)} {(SQ <"Unpartitioned space">)}) ] negated: False ) ] ) left_token: spids: [359 375] ) } spids: [358] ) ] spids: [358] ) (C {(printf)} { (DQ ("Resizing disk partition: ") ($ VSub_Name "$SPACE") (EscapedLiteralPart token:) ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:START) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(sfdisk)} {(-J)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(jq)} {(-e)} { (SQ < ".partitiontable.partitions | map(select(.type==\"83\")) | .[0].start" > ) } ) ] negated: False ) ] ) left_token: spids: [393 411] ) } spids: [392] ) ] spids: [392] ) (SimpleCommand words: [{(sfdisk)} {(-q)} {(--delete)} {(DQ ($ VSub_Name "$DRIVE"))}] redirects: [(Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[425])] ) (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name START) (",,83;"))}) (C {(sfdisk)} {(-q)} {(DQ ($ VSub_Name "$DRIVE"))}) ] negated: False ) (C {(sfdisk)} {(-A)} {(DQ ($ VSub_Name "$DRIVE"))} {(1)}) (SimpleCommand words: [{(blockdev)} {(--rereadpt)} {($ VSub_Name "$diskdev")}] redirects: [(Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[477])] ) (C {(mdev)} {(-s)}) (ForEach iter_name: i iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(seq)} {(1)} {(50)})]) left_token: spids: [498 504] ) } ] do_arg_iter: False body: (DoGroup children: [ (Sentence child: (AndOr children: [ (C {(test)} {(-b)} {(DQ ($ VSub_Name "$DATA"))}) (AndOr children: [ (ControlFlow token: ) (C {(sleep)} {(.1)}) ] op_id: Op_DPipe ) ] op_id: Op_DAmp ) terminator: ) (Sentence child: (C {(mdev)} {(-s)}) terminator: ) ] spids: [507 533] ) spids: [497 505] ) (AndOr children: [ (C {(do_fsck)} {(-f)} {(DQ ($ VSub_Name "$DATA"))}) (ControlFlow token: arg_word: {(1)} ) ] op_id: Op_DPipe ) (C {(resize2fs)} {(DQ ($ VSub_Name "$DATA"))}) (AndOr children: [ (C {(do_fsck)} {(DQ ($ VSub_Name "$DATA"))}) (ControlFlow token: arg_word: {(1)} ) ] op_id: Op_DPipe ) ] spids: [-1 355] ) ] spids: [-1 577] ) ] spids: [240] ) spids: [236 239] ) (FuncDef name: do_mkfs body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:diskdev) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [589] ) ] spids: [589] ) (Pipeline children: [ (C {(echo)} {(DQ (w))}) (SimpleCommand words: [{(fdisk)} {($ VSub_Name "$diskdev")}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[624])] ) ] negated: False ) (Pipeline children: [(C {(echo)} {(DQ (";"))}) (C {(sfdisk)} {(--quiet)} {($ VSub_Name "$diskdev")})] negated: False ) (SimpleCommand words: [{(blockdev)} {(--rereadpt)} {($ VSub_Name "$diskdev")}] redirects: [(Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[659])] ) (ForEach iter_name: i iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(seq)} {(1)} {(50)})]) left_token: spids: [675 681] ) } ] do_arg_iter: False body: (DoGroup children: [ (Sentence child: (AndOr children: [ (C {(test)} {(-b)} {(DQ ($ VSub_Name "$DATA"))}) (AndOr children: [ (ControlFlow token: ) (C {(sleep)} {(.1)}) ] op_id: Op_DPipe ) ] op_id: Op_DAmp ) terminator: ) (Sentence child:(C {(mdev)} {(-s)}) terminator:) ] spids: [684 710] ) spids: [674 682] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:FSOPTS) op: Equal rhs: { (DQ ( "-O resize_inode,has_journal,extent,huge_file,flex_bg,uninit_bg,64bit,dir_nlink,extra_isize" ) ) } spids: [714] ) ] spids: [714] ) (C {(mkfs.ext4)} {(-q)} {(-F)} {($ VSub_Name "$FSOPTS")} {(${ VSub_Name diskdev) (1)}) ] spids: [586] ) spids: [582 585] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DEV) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(find)} {(/dev)} {(-maxdepth)} {(1)} {(-type)} {(b)} {(KW_Bang "!")} {(-name)} {(SQ <"loop*">)} ) (C {(grep)} {(-v)} {(SQ <"[0-9]$">)}) (C {(sed)} {(SQ <"s@.*/dev/@@">)}) (C {(sort)}) (C {(head)} {(-1)}) ] negated: False ) ] ) left_token: spids: [742 791] ) ) } spids: [740] ) ] spids: [740] ) (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ (${ VSub_Name DEV))} {(Lit_Other "]")}) (C {(exit)} {(1)}) ] op_id: Op_DAmp ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DRIVE) op: Equal rhs: {(DQ (/dev/) (${ VSub_Name DEV))} spids: [814] ) ] spids: [814] ) (If arms: [ (if_arm cond: [ (SimpleCommand words: [{(sfdisk)} {(-d)} {(DQ (${ VSub_Name DRIVE))}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[838]) (Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[841]) ] ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DATA) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(sfdisk)} {(-J)} {(DQ ($ VSub_Name "$DRIVE"))}) (C {(jq)} {(-e)} {(-r)} { (SQ < ".partitiontable.partitions | map(select(.type==\"83\")) | .[0].node" > ) } ) ] negated: False ) ] ) left_token: spids: [848 868] ) } spids: [847] ) ] spids: [847] ) (If arms: [ (if_arm cond: [(C {(Lit_Other "[")} {($ VSub_QMark "$?")} {(-eq)} {(0)} {(Lit_Other "]")})] action: [ (AndOr children: [ (C {(do_fsck_extend_mount)} {(DQ ($ VSub_Name "$DRIVE"))} {(DQ ($ VSub_Name "$DATA"))} ) (C {(do_mkfs)} {(DQ ($ VSub_Name "$DRIVE"))}) ] op_id: Op_DPipe ) ] spids: [-1 884] ) ] else_action: [(C {(do_mkfs)} {(DQ ($ VSub_Name "$DRIVE"))})] spids: [906 916] ) ] spids: [-1 844] ) ] else_action: [(C {(do_mkfs)} {(DQ ($ VSub_Name "$DRIVE"))})] spids: [918 927] ) ] )