#!/usr/bin/wish -f # File system tool # (C) Copyright 1994 by Red Hat Software if {[catch set env(CONTROL_PANEL_LIB_DIR)] != 0} { set env(CONTROL_PANEL_LIB_DIR) /usr/lib/rhs/control-panel } if {[catch {source $env(CONTROL_PANEL_LIB_DIR)/dialog.tcl}] != 0} { puts "Couldn't load dialog.tcl" puts "Start from control-panel or set environment variable" puts "CONTROL_PANEL_LIB_DIR to the control-panel library dir." puts "(normally this is /usr/lib/rhs/control-panel)" exit 0 } if {[catch {source $env(CONTROL_PANEL_LIB_DIR)/bindings.tcl}] != 0} { puts "Couldn't load bindings.tcl" puts "Start from control-panel or set environment variable" puts "CONTROL_PANEL_LIB_DIR to the control-panel library dir." puts "(normally this is /usr/lib/rhs/control-panel)" exit 0 } ######################################################### ## @@ Random Data # trigger is used to watch for "OK" and "Cancel" presses set trigger 0 set selected_type "" set selected_hint "" set delete_index "" set fsck "$env(CONTROL_PANEL_LIB_DIR)/fstool-aux fsck" set mkfs "$env(CONTROL_PANEL_LIB_DIR)/fstool-aux mkfs" set short_partitiontype(Empty) EMTY set short_partitiontype(AIX) AIX set short_partitiontype(PC/IX) PCIX set short_partitiontype(BSDI_swap) BSDS set short_partitiontype(DOS_12-bit_FAT) DS12 set short_partitiontype(AIX_bootable) AIXB set short_partitiontype(Old_MINIX) OMNX set short_partitiontype(Syrinx) SYRX set short_partitiontype(XENIX_root) XNXR set short_partitiontype(OPUS) OPUS set short_partitiontype(Linux/MINIX) LINM set short_partitiontype(CP/M) CPM set short_partitiontype(XENIX_usr) XNXU set short_partitiontype(Venix_80286) VNX set short_partitiontype(Linux_swap) LNXS set short_partitiontype(DOS_access) DOSA set short_partitiontype(DOS_16-bit_<32M) DOS< set short_partitiontype(Novell) NOVL set short_partitiontype(Linux_native) LNUX set short_partitiontype(DOS_R/O) DOSR set short_partitiontype(Extended) EXTD set short_partitiontype(Microport) MPRT set short_partitiontype(Amoeba) AMBA set short_partitiontype(DOS_secondary) DOS2 set short_partitiontype(DOS_16-bit_>=32) DOS> set short_partitiontype(GNU_HURD) HURD set short_partitiontype(Amoeba_BBT) AMBB set short_partitiontype(BBT) BBT set short_partitiontype(OS/2_HPFS) OS2 set short_partitiontype(Novell) NOVL set short_partitiontype(BSDI_fs) BSDF set short_partitiontype(nfs) NFS set short_partitiontype(na) NA set short_partitiontype(unknown) UKNN set long_partitiontype(Empty) "Empty" set long_partitiontype(AIX) "AIX" set long_partitiontype(PC/IX) "PC/IX" set long_partitiontype(BSDI_swap) "BSDI swap" set long_partitiontype(DOS_12-bit_FAT) "DOS 12-bit FAT" set long_partitiontype(AIX_bootable) "AIX bootable" set long_partitiontype(Old_MINIX) "Old MINIX" set long_partitiontype(Syrinx) "Syrinx" set long_partitiontype(XENIX_root) "XENIX root" set long_partitiontype(OPUS) "OPUS" set long_partitiontype(Linux/MINIX) "Linux/MINIX" set long_partitiontype(CP/M) "CP/M" set long_partitiontype(XENIX_usr) "XENIX usr" set long_partitiontype(Venix_80286) "Venix 80286" set long_partitiontype(Linux_swap) "Linux swap" set long_partitiontype(DOS_access) "DOS access" set long_partitiontype(DOS_16-bit_<32M) "DOS 16-bit <32M" set long_partitiontype(Novell) "Novell" set long_partitiontype(Linux_native) "Linux native" set long_partitiontype(DOS_R/O) "DOS R/O" set long_partitiontype(Extended) "Extended" set long_partitiontype(Microport) "Microport" set long_partitiontype(Amoeba) "Amoeba" set long_partitiontype(DOS_secondary) "DOS secondary" set long_partitiontype(DOS_16-bit_>=32) "DOS 16-bit >=32" set long_partitiontype(GNU_HURD) "GNU HURD" set long_partitiontype(Amoeba_BBT) "Amoeba BBT" set long_partitiontype(BBT) "BBT" set long_partitiontype(OS/2_HPFS) "OS/2 HPFS" set long_partitiontype(Novell) "Novell" set long_partitiontype(BSDI_fs) "BSDI fs" set long_partitiontype(nfs) "Network File System" set long_partitiontype(na) "Not Applicable" set long_partitiontype(unknown) "Unknown" ######################################################### ## @@ User interface frame .menuf -relief raised -borderwidth 2 menubutton .menuf.fsm -text "FSM" -menu .menuf.fsm.menu menu .menuf.fsm.menu .menuf.fsm.menu add command -label "Reload" -command menu_reload .menuf.fsm.menu add command -label "Set Options" -command menu_options .menuf.fsm.menu add separator #.menuf.fsm.menu add command -label "About" -command menu_about #.menuf.fsm.menu add separator .menuf.fsm.menu add command -label "Add Mount" -command menu_fsm_add_mount .menuf.fsm.menu add command -label "Delete Mount" -command menu_fsm_delete_mount .menuf.fsm.menu add separator .menuf.fsm.menu add command -label "Quit" -command menu_quit menubutton .menuf.nfs -text "NFS" -menu .menuf.nfs.menu menu .menuf.nfs.menu .menuf.nfs.menu add command -label "Add Mount" -command menu_nfs_add_mount .menuf.nfs.menu add command -label "Delete Mount" -command menu_nfs_delete_mount .menuf.nfs.menu add command -label "Edit Exports" -command menu_nfs_edit_exports pack .menuf.fsm .menuf.nfs -side left -in .menuf tk_menuBar .menuf .menuf.fsm .menuf.nfs label .header -font fixed -text "Header stuff" -anchor w frame .main -relief sunken -borderwidth 2 listbox .list -font fixed -yscrollcommand ".sb set" -setgrid 1 -exportselection 0 -selectmode single scrollbar .sb -command ".list yview" pack .list -side left -expand true -fill both -in .main pack .sb -side left -fill y -in .main frame .buttons button .info -text "Info" -width 10 -command button_info button .fsck -text "Check" -width 10 -command button_fsck button .mount -text "Mount" -width 10 -command button_mount button .umount -text "Unmount" -width 10 -command button_umount button .mkfs -text "Format" -width 10 -command button_mkfs button .edit -text "Edit" -width 10 -command button_edit pack .info .fsck .mount .umount .mkfs .edit -side left -expand true -ipady 1 -in .buttons pack .menuf -side top -fill x # The following large padx is so that the header # lines up properly with the stuff in the listbox pack .header -side top -fill x -padx 8 pack .main -side top -expand true -fill both -padx 4 pack .buttons -side top -fill x -padx 4 -pady 4 wm minsize . 20 10 wm title . "RHS Linux File System Manager" bind .list " .list selection clear 0 end .list selection set \[.list nearest %y\] button_edit " ## End of main user interface ########################################################### ## @@ Random Functions proc getfsindex {fsn} { global fscount fsname for {set i 0} {$i < $fscount} {incr i} { if {$fsname($i) == $fsn} { return $i } } return -1 } proc reload {} { global fscount global fsname fspartitiontype global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fsmounted global fstab fstabmountpoint fstabfstype fstabopts fstabcomment global fstabdump fstabfsck # First we load stuff from dfplus set fd [open "| dfplus" r] set fscount 0 while {[gets $fd s] != "-1"} { set fsname($fscount) [lindex $s 0] set fspartitiontype($fscount) [lindex $s 1] set fssize($fscount) [lindex $s 2] set fsused($fscount) [lindex $s 3] set fsavail($fscount) [lindex $s 4] set fscapacity($fscount) [lindex $s 5] set fsmountpoint($fscount) [lindex $s 6] if {$fsmountpoint($fscount) != ""} { set fsmounted($fscount) "*" } else { set fsmountpoint($fscount) "none" set fsmounted($fscount) " " } set fsopts($fscount) [lindex $s 7] # Set these up for later set fstabdump($fscount) 0 set fstabfsck($fscount) 0 set fstab($fscount) " " set fstabmountpoint($fscount) "" if [regexp HPFS $fspartitiontype($fscount)] { set fstabfstype($fscount) hpfs set fstabopts($fscount) "defaults" } else { set fstabfstype($fscount) ignore set fstabopts($fscount) "" } set fstabcomment($fscount) "" incr fscount } close $fd # Now we read in /etc/fstab set fd [open "/etc/fstab" r] while {[gets $fd s] != "-1"} { if {[llength $s] == 0} { continue } set cp [lindex $s 0] set valid_comment 0 if {[regexp "^\#" $cp] == 1} { # First check for a comment set valid_comment [regexp "\#% (.*)" $s bogus comment] continue } set i [getfsindex $cp] if {$i == -1} { # Set this here so we can over-ride it set i $fscount set fspartitiontype($i) "nfs" # This is entry was not found by dfplus # It is probably an NFS partition, a partition that was deleted, # or another device (like a floppy) # If not NFS, ask user if we should delete it. if {[lindex $s 2] != "nfs" && ([string match "/dev/hd??*" $cp] || [string match "/dev/sd??*" $cp])} { set nt "Partition $cp seems to have been deleted.\nShall I remove it from /etc/fstab ?" if {[rhs_dialog .r "Notice" $nt question 0 "Remove It" "Leave It"] == 0} { continue } set fspartitiontype($i) "na" } incr fscount # Fill in some stuff set fsname($i) $cp set fsmounted($i) " " set fsmountpoint($i) "none" set fstabfstype($i) "ignore" set fssize($i) "na" set fsused($i) "na" set fsavail($i) "na" set fscapacity($i) "na" set fsopts($i) "na" } set fstab($i) "F" set fstabmountpoint($i) [lindex $s 1] if { $fstabfstype($i) == "ignore" } { set fstabfstype($i) [lindex $s 2] set fstabopts($i) [lindex $s 3] } # Set the new dump and fsck options here set fstabdump($i) [lindex $s 4] if {$fstabdump($i) == ""} { set fstabdump($i) 0 } set fstabfsck($i) [lindex $s 5] if {$fstabfsck($i) == ""} { set fstabfsck($i) 0 } # Set mount point if we don't have it already # From this point on, we only care about fsmountpoint if {$fsmountpoint($i) == "none"} { set fsmountpoint($i) $fstabmountpoint($i) } # Fix values for proc filesystem if {$fstabfstype($i) == "proc"} { set fspartitiontype($i) "na" set fssize($i) "na" set fsused($i) "na" set fsavail($i) "na" set fscapacity($i) "na" } if {$valid_comment == 1} { set valid_comment 0 set fstabcomment($i) $comment } else { set fstabcomment($i) "" } } close $fd } proc gen_format {} { global options global header_string global format_string eval_string set es {$fsname($i) $fsmountpoint($i) $fsmounted($i)} set fs "%-15s %-15s %1.1s" set hs [format $fs "Device" "Mount Point" M] if {$options(fstabfstype) == 1} { append es " " {$fstabfstype($i)} set fs "$fs %-7s" set hs "$hs [format "%-7s" "Type"]" } if {$options(fspartitiontype) == 1} { append es " " {$fspartitiontype($i)} set fs "$fs %-15s" set hs "$hs [format "%-15s" "Partition Type"]" } if {$options(fssize) == 1} { append es " " {$fssize($i)} set fs "$fs %7s" set hs "$hs [format "%7s" "Size"]" } if {$options(fsused) == 1} { append es " " {$fsused($i)} set fs "$fs %7s" set hs "$hs [format "%7s" "Used"]" } if {$options(fsavail) == 1} { append es " " {$fsavail($i)} set fs "$fs %7s" set hs "$hs [format "%7s" "Avail"]" } if {$options(fscapacity) == 1} { append es " " {$fscapacity($i)} set fs "$fs %3s" set hs "$hs [format "%3s" "%"]" } if {$options(fstabopts) == 1} { append es " " {$fstabopts($i)} set fs "$fs %-15s" set hs "$hs [format "%-15s" "fstab Options"]" } if {$options(fsopts) == 1} { append es " " {$fsopts($i)} set fs "$fs %-15s" set hs "$hs [format "%-15s" "Mounted Options"]" } if {$options(fstabcomment) == 1} { append es " " {$fstabcomment($i)} set fs "$fs %s" set hs "$hs [format "%s" "Comment"]" } set eval_string $es set format_string $fs set header_string $hs } proc redisplay {} { global fscount global fsname fspartitiontype global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fsmounted fstab global fstab fstabmountpoint fstabfstype fstabopts fstabcomment global options header_string format_string eval_string global selected_hint .header configure -text $header_string set selected_name $selected_hint # set selected_offset [expr [lindex [.sb get] 1] * [.list] set cs [.list curselection] if {$cs != ""} { if {$selected_name == ""} { set selected_name [lindex [.list get $cs] 0] } # set selected_offset [expr $cs - [lindex [.sb get] 2]] } .list delete 0 end set selected_index -1 for {set i 0} {$i < $fscount} {incr i} { .list insert end [eval format \"$format_string\" $eval_string] if {$selected_name == $fsname($i)} { set selected_index $i } } if {$selected_index != -1} { .list select set $selected_index .list see $selected_index } set selected_hint "" } proc sort_by_fsmountpoint {a b} { global fsmountpoint string compare $fsmountpoint($a) $fsmountpoint($b) } proc write_fstab {} { global fscount global fsname fspartitiontype global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fsmounted fstab global fstab fstabmountpoint fstabfstype fstabopts fstabcomment global options header_string format_string eval_string global delete_index global fstabdump fstabfsck # First write the header # Then all regular filesystems # Then swap partitions # Then extended partitions # Then NFS mounts # delete_index only pertains to NFS mounts set fd [open "/etc/fstab" w] puts $fd "\#" puts $fd "\# /etc/fstab" puts $fd "\#" puts $fd "\# You should be using fstool (control-panel) to edit this!" puts $fd "\#" puts $fd "\# " puts $fd "" # We have to write fstabopts *not* fsopts # These entries need to be sorted by mount point set indexes "" for {set i 0} {$i < $fscount} {incr i} { if {$fstabfstype($i) != "swap" && \ $fstabfstype($i) != "na" && \ $fstabfstype($i) != "" && \ $fstabfstype($i) != "proc"} { catch {exec mkdir -p $fsmountpoint} } if {$fstabfstype($i) != "swap" && \ $fstabfstype($i) != "na" && \ $fstabfstype($i) != "" && \ $fstabfstype($i) != "proc" && \ $fstabfstype($i) != "nfs"} { if {$i == $delete_index} { continue } set indexes "$indexes $i" } } foreach i [lsort -command sort_by_fsmountpoint $indexes] { if {$fstabcomment($i) != ""} { puts $fd "\#% $fstabcomment($i)" } puts $fd [format "%-25s %-25s %-6s %s %d %d" $fsname($i) \ $fsmountpoint($i) $fstabfstype($i) $fstabopts($i) \ $fstabdump($i) $fstabfsck($i)] } puts $fd "" for {set i 0} {$i < $fscount} {incr i} { if {$fstabfstype($i) == "proc"} { if {$i == $delete_index} { continue } if {$fstabcomment($i) != ""} { puts $fd "\#% $fstabcomment($i)" } puts $fd [format "%-25s %-25s proc %s" \ $fsname($i) $fsmountpoint($i) \ $fstabopts($i)] } } for {set i 0} {$i < $fscount} {incr i} { if {$fstabfstype($i) == "swap"} { if {$i == $delete_index} { continue } if {$fstabcomment($i) != ""} { puts $fd "\#% $fstabcomment($i)" } puts $fd [format "%-25s none swap sw" $fsname($i)] } } puts $fd "" for {set i 0} {$i < $fscount} {incr i} { if {$fstabfstype($i) == "na" || $fstabfstype($i) == ""} { if {$i == $delete_index} { continue } if {$fstabcomment($i) != ""} { puts $fd "\#% $fstabcomment($i)" } puts $fd [format "%-25s %-25s ignore %s" $fsname($i) $fsmountpoint($i) \ $fstabopts($i)] } } for {set i 0} {$i < $fscount} {incr i} { if {$fstabfstype($i) == "nfs"} { if {$i == $delete_index} { continue } if {$fstabcomment($i) != ""} { puts $fd "\#% $fstabcomment($i)" } puts $fd [format "%-25s %-25s nfs %s" $fsname($i) $fsmountpoint($i) \ $fstabopts($i)] } } close $fd set delete_index "" } proc sync {} { write_fstab reload write_fstab redisplay } proc get_selected_index {} { return [.list curselection] } proc bind_entries_for_traversal {l} { set count [llength $l] lappend l [lindex $l 0] for {set i 0} {$i < $count} {incr i} { set from [lindex $l $i] set to [lindex $l [expr $i + 1]] set_emacs_entry_bindings $from bind $from "focus $to" bind $from "focus $to" } } proc info_or_edit {t i} { global trigger global long_partitiontype global fsname fspartitiontype global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fsmounted fstab global fstab fstabmountpoint fstabfstype fstabopts fstabcomment global selected_hint # Edit -> fstabcomment fstabopts fsmountpoint # For mounted filessytem, can only edit fstabcomment # If y != "" then edit fsname fstabfstype set nothdsd "y" if {[string match "/dev/hd*" $fsname($i)] || [string match "/dev/sd*" $fsname($i)]} { set nothdsd "n" } set mounted $fsmounted($i) # For swap and extended partitions can only edit comment # We check swap against fstabfstype because the tag on # the partition doesn't really mean anything. if {$fspartitiontype($i) == "Extended" || $fstabfstype($i) == "swap"} { # Just pretend it's mounted set mounted "*" } toplevel .e wm withdraw .e if {$t == "e"} { wm title .e "Edit Filesystem" } else { wm title .e "FS Info" } frame .e.f1 frame .e.f2 set traversal_list "" label .e.l1 -text "Device" -anchor w if {$mounted != "*" && $t == "e" && ($fstabfstype($i) == "nfs" || $nothdsd == "y")} { # editable device or NFS entry .e.v1 -font fixed -relief sunken -borderwidth 2 lappend traversal_list .e.v1 } else { label .e.v1 -text "$fsname($i)" -anchor w -font fixed } label .e.l2 -text "Partition Type" -anchor w label .e.v2 -text "$long_partitiontype($fspartitiontype($i))" -anchor w -font fixed label .e.l3 -text "FS Type" -anchor w if {$mounted != "*" && $nothdsd == "y" && $fstabfstype($i) != "nfs"} { entry .e.v3 -font fixed -relief sunken -borderwidth 2 lappend traversal_list .e.v3 } else { label .e.v3 -text "$fstabfstype($i)" -anchor w -font fixed } label .e.l4 -text "Mount Point" -anchor w label .e.l5 -text "Mount Options" -anchor w label .e.l51 -text "Current Options" -anchor w label .e.l6 -text "Comment" -anchor w label .e.l7 -text "Size" -anchor w label .e.l8 -text "Used" -anchor w label .e.l9 -text "Available" -anchor w label .e.l0 -text "Percent Used" -anchor w if {$mounted == "*" || $t != "e"} { label .e.v4 -font fixed -anchor w -text "$fsmountpoint($i)" label .e.v5 -font fixed -anchor w -text "$fstabopts($i)" } else { entry .e.v4 -font fixed -relief sunken -borderwidth 2 entry .e.v5 -font fixed -relief sunken -borderwidth 2 lappend traversal_list .e.v4 lappend traversal_list .e.v5 } label .e.v51 -font fixed -anchor w -text "$fsopts($i)" if {$t == "e"} { entry .e.v6 -font fixed -relief sunken -borderwidth 2 lappend traversal_list .e.v6 } else { label .e.v6 -font fixed -anchor w -text "$fstabcomment($i)" } label .e.v7 -font fixed -anchor w -text "$fssize($i)" label .e.v8 -font fixed -anchor w -text "$fsused($i)" label .e.v9 -font fixed -anchor w -text "$fsavail($i)" label .e.v0 -font fixed -anchor w -text "$fscapacity($i)" if {$t == "e"} { if {$mounted != "*"} { .e.v4 insert 0 $fsmountpoint($i) .e.v5 insert 0 $fstabopts($i) if {$fstabfstype($i) == "nfs" || $nothdsd == "y"} { .e.v1 insert 0 $fsname($i) } if {$fstabfstype($i) != "nfs" && $nothdsd == "y"} { .e.v3 insert 0 $fstabfstype($i) } } .e.v6 insert 0 $fstabcomment($i) } pack .e.l1 .e.l2 .e.l3 .e.l4 .e.l5 \ .e.l51 .e.l6 .e.l7 .e.l8 .e.l9 .e.l0 \ -side top -expand true -fill x -in .e.f1 pack .e.v1 .e.v2 .e.v3 .e.v4 .e.v5 \ .e.v51 .e.v6 .e.v7 .e.v8 .e.v9 .e.v0 \ -side top -expand true -fill x -in .e.f2 frame .e.buttons button .e.b1 -text "OK" -width 10 -command "set trigger 1" pack .e.b1 -side left -expand true -ipady 1 -in .e.buttons if {$t == "e"} { button .e.b2 -text "Cancel" -width 10 -command "set trigger 0" pack .e.b2 -side left -expand true -ipady 1 -in .e.buttons } pack .e.buttons -side bottom -expand true -fill x -padx 4 -pady 4 -in .e pack .e.f1 .e.f2 -side left -expand true -fill both -padx 2 -pady 1 -in .e if {$t == "e"} { bind_entries_for_traversal $traversal_list } center_dialog .e grab set .e tkwait variable trigger if {$t == "e" && $trigger == 1} { # Get values if {$mounted != "*"} { set fsmountpoint($i) [.e.v4 get] set fstabopts($i) [.e.v5 get] if {$fstabfstype($i) == "nfs" || $nothdsd == "y"} { set fsname($i) [.e.v1 get] } if {$fstabfstype($i) != "nfs" && $nothdsd == "y"} { set fstabfstype($i) [.e.v3 get] } } set fstabcomment($i) [.e.v6 get] destroy .e set selected_hint $fsname($i) } else { destroy .e } return $trigger } ## End of random functions ############################################## ## @@ User Interface callback functions proc menu_nfs_edit_exports {} { rhs_info_dialog " Editing of /etc/exports is not supported at this time. When editing /etc/exports remember that nfsd is accessed through portmap, which in turn uses /etc/hosts.allow and /etc/hosts.deny for access control. In order for a host to mount an exported filesystem, it must be allowed portmap access in /etc/hosts.allow, and nfsd access in /etc/exports. " } proc button_info {} { set i [get_selected_index] if {$i == ""} { return } info_or_edit t $i } proc button_edit {} { set i [get_selected_index] if {$i == ""} { return } if {[info_or_edit e $i] == 1} { sync } } proc button_umount {} { global fsname fsmounted fstabfstype selected_hint set i [get_selected_index] if {$i == ""} { return } if {$fstabfstype($i) != "swap"} { # Must be mounted if {$fsmounted($i) != "*"} { rhs_error_dialog "$fsname($i) is not mounted" return } set res [catch {exec umount $fsname($i)} error_string] if {$res != 0} { rhs_error_dialog "umount $fsname($i)\n\nreturned the following error:\n\n$error_string" update idletasks } } else { # swapoff set res [catch {exec swapoff $fsname($i)} error_string] if {$res != 0} { rhs_error_dialog "swapoff $fsname($i)\n\nreturned the following error:\n\n$error_string\n\n(It's probably not in swap space)" } else { rhs_info_dialog "Device $fsname($i) removed from swap space." } update idletasks } set selected_hint $fsname($i) sync } proc button_mount {} { global fsname fsmounted fstabfstype selected_hint set i [get_selected_index] if {$i == ""} { return } # Must not already be mounted if {$fsmounted($i) == "*"} { rhs_error_dialog "$fsname($i) is already mounted" return } # Must not have fstabfstype of ignore if {$fstabfstype($i) == "ignore"} { rhs_error_dialog "Can't mount $fsname($i)\nIts FS Type is $fstabfstype($i)" return } if {$fstabfstype($i) != "swap"} { set res [catch {exec mount $fsname($i)} error_string] if {$res != 0} { rhs_error_dialog "mount $fsname($i)\n\nreturned the following error:\n\n$error_string" update idletasks } } else { # swapon set res [catch {exec swapon $fsname($i)} error_string] if {$res != 0} { rhs_error_dialog "swapon $fsname($i)\n\nreturned the following error:\n\n$error_string\n\n(It's probably already added to swap space)" } else { rhs_info_dialog "Device $fsname($i) added to swap space." } update idletasks } set selected_hint $fsname($i) sync } proc button_fsck {} { global fsmounted fsopts fstabfstype fsname fsck # fstool.fsck -af $fsname($i) # display output set i [get_selected_index] if {$i == ""} { return } # Must be ext2 or minix if {$fstabfstype($i) != "ext2" && $fstabfstype($i) != "minix"} { rhs_error_dialog "Can only check ext2 and minix filesystems" return } # Must either be unmounted or mounted ro if {$fsmounted($i) == "*"} { # Check for read only set opts [split $fsopts($i) ","] if {[lsearch -exact $opts "ro"] == -1} { rhs_error_dialog "You can not check a filesystem mounted read-write.\nUnmount it before checking." return } } catch {eval exec $fsck -af $fsname($i)} output rhs_dialog .o "fsck output" $output info 0 "OK" } proc button_mkfs {} { global fsmounted fsname fspartitiontype fstabfstype fssize global selected_type trigger mkfs fstabopts # Offer fs types (ext2, minix) # mkfs -t $fsname($i) set i [get_selected_index] if {$i == ""} { return } # Must not be mounted if {$fsmounted($i) == "*"} { rhs_error_dialog "Can not make a file system\non a mounted partition." return } # Must not be nfs or extended if {$fspartitiontype($i) == "nfs" || $fspartitiontype($i) == "Extended"} { rhs_error_dialog "Can not make a file system on\nnfs or extended \"partitions\"" return } # Warn if already has fstabfstype (probably already formated) if {$fstabfstype($i) != "ignore"} { if {$fstabfstype($i) == "swap"} { set res [rhs_continue_dialog "This appears to be a swap partition.\nI will attempt to \"swapoff\" this partition\nbefore continuing."] } else { set res [rhs_continue_dialog "This partition appears to already have been\nformatted. Do you wish to continue?"] } if {$res == 1} { return } } if {$fstabfstype($i) == "swap"} { catch {exec swapoff $fsname($i)} } set selected_type ext2 toplevel .o wm withdraw .o wm title .o "Filesystem Type" label .o.l -text "Please choose a filesystem type" pack .o.l -side top -expand true -fill both -in .o radiobutton .o.r1 -text "Extended 2" -variable selected_type -value ext2 radiobutton .o.r2 -text "Minix" -variable selected_type -value minix radiobutton .o.r3 -text "Swap" -variable selected_type -value swap pack .o.r1 .o.r2 .o.r3 -side top -expand true -fill both -in .o button .o.ok -text "OK" -width 10 -command "set trigger 1" button .o.cancel -text "Cancel" -width 10 -command "set trigger 0" pack .o.ok .o.cancel -side left -expand true -padx 4 -pady 4 -in .o center_dialog .o grab set .o tkwait variable trigger destroy .o if {$trigger == 1} { set fstabfstype($i) $selected_type set res [catch {eval exec $mkfs -t $selected_type $fsname($i) $fssize($i)} error_string] if {$selected_type == "swap"} { set fstabopts($i) "sw" } else { set fstabopts($i) "defaults" } if {$res != 0} { if {$selected_type == "swap"} { rhs_error_dialog "mkswap $fsname($i) $fssize($i)\n\nreturned the following error:\n\n$error_string" } else { rhs_error_dialog "mkfs -t $selected_type $fsname($i) $fssize($i)\n\nreturned the following error:\n\n$error_string" } # safety value set fstabfstype($i) "ignore" update idletasks } sync } } proc menu_options {} { global options toplevel .o wm withdraw .o wm title .o "Display Options" checkbutton .o.b1 -text "File System Type" -variable options(fstabfstype) -anchor w checkbutton .o.b2 -text "Partition Type" -variable options(fspartitiontype) -anchor w checkbutton .o.b3 -text "Size" -variable options(fssize) -anchor w checkbutton .o.b4 -text "Used" -variable options(fsused) -anchor w checkbutton .o.b5 -text "Avail" -variable options(fsavail) -anchor w checkbutton .o.b6 -text "% Used" -variable options(fscapacity) -anchor w checkbutton .o.b7 -text "/etc/fstab Options" -variable options(fstabopts) -anchor w checkbutton .o.b8 -text "Mounted Options" -variable options(fsopts) -anchor w checkbutton .o.b9 -text "Comment" -variable options(fstabcomment) -anchor w button .o.ok -text "OK" -width 10 -command "destroy .o" pack .o.b1 .o.b2 .o.b3 .o.b4 .o.b5 .o.b6 .o.b7 .o.b8 .o.b9 -side top -expand true -fill x -padx 2 -pady 1 pack .o.ok -expand true -padx 4 -pady 4 center_dialog .o grab set .o tkwait window .o gen_format redisplay } proc menu_fsm_add_mount {} { global fsname fspartitiontype fscount global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fstabmountpoint fstabfstype fstabopts fstabcomment global fsmounted fstab global fstabdump fstabfsck set i $fscount incr fscount set fsname($i) "" set fspartitiontype($i) "na" set fstabfstype($i) "" set fsmountpoint($i) "none" set fstabmountpoint($i) "none" set fstabopts($i) "defaults" set fsopts($i) "na" set fstabcomment($i) "" set fssize($i) "na" set fsused($i) "na" set fsavail($i) "na" set fscapacity($i) "na" set fstabdump($i) "0" set fstabfsck($i) "0" set fsmounted($i) " " set fstab($i) " " if {[info_or_edit e $i] == 1} { sync } else { incr fscount -1 } } proc menu_nfs_add_mount {} { global fsname fspartitiontype fscount global fssize fsused fsavail fscapacity global fsmountpoint fsopts global fstabmountpoint fstabfstype fstabopts fstabcomment global fsmounted fstab set i $fscount incr fscount set fsname($i) "host:path" set fspartitiontype($i) "nfs" set fstabfstype($i) "nfs" set fsmountpoint($i) "none" set fstabmountpoint($i) "none" set fstabopts($i) "soft,intr,rw" set fsopts($i) "na" set fstabcomment($i) "" set fssize($i) "na" set fsused($i) "na" set fsavail($i) "na" set fscapacity($i) "na" set fsmounted($i) " " set fstab($i) " " if {[info_or_edit e $i] == 1} { sync } else { incr fscount -1 } } proc menu_nfs_delete_mount {} { global delete_index fstabfstype fsmounted fsname set i [.list curselection] if {$i == ""} { rhs_error_dialog "No NFS filesystem selected" return } if {$fstabfstype($i) != "nfs"} { rhs_error_dialog "That is not an NFS filesystem" return } if {$fsmounted($i) == "*"} { rhs_error_dialog "You can't delete a mounted filesystem" return } set res [rhs_continue_dialog "Delete NFS filesystem $fsname($i)\nfrom /etc/fstab?"] if {$res == 1} { return } set delete_index $i # sync writes /etc/fstab first, so this will do sync } proc menu_fsm_delete_mount {} { global delete_index fstabfstype fsmounted fsname set i [.list curselection] if {$i == ""} { rhs_error_dialog "No filesystem selected" return } if {$fstabfstype($i) == "nfs" || [string match "/dev/hd*" $fsname($i)] || [string match "/dev/sd*" $fsname($i)]} { rhs_error_dialog "You can't delete a NFS filesystem or hard drive partition" return } if {$fsmounted($i) == "*"} { rhs_error_dialog "You can't delete a mounted filesystem" return } set res [rhs_continue_dialog "Delete filesystem $fsname($i)\nfrom /etc/fstab?"] if {$res == 1} { return } set delete_index $i # sync writes /etc/fstab first, so this will do sync } proc menu_about {} { puts "About what?" } proc menu_quit {} { # We could sync here but we should always be synced exit 0 } proc menu_reload {} { global selected_hint # Maintain selection if there is one set i [.list curselection] if {$i != ""} { set selected_hint [lindex [.list get [.list curselection]] 0] } .list delete 0 end update idletasks # We don't need to (and should not) write out fstab # since we should always be synced, and the goal # is really to pick up any external changes reload redisplay } ## End of user interface callback functions ############################################# ## @@ main program set options(fstabfstype) 1 set options(fspartitiontype) 0 set options(fssize) 1 set options(fsused) 0 set options(fsavail) 1 set options(fscapacity) 0 set options(fstabopts) 0 set options(fsopts) 0 set options(fstabcomment) 1 if {[exec id -u] != 0} { rhs_error_dialog "You must be root to run the File System Tool." exit 1 } # We can't call sync right away or /etc/fstab will get clobbered if {[file exists /etc/fstab.bak] == 1} { if {[rhs_yesno_dialog "/etc/fstab.bak exists.\n\nOverwrite it?" 1] == 0} { exec /bin/cp -f /etc/fstab /etc/fstab.bak } } else { exec /bin/cp -f /etc/fstab /etc/fstab.bak } reload write_fstab gen_format redisplay