1 1.1 haad #!/bin/sh 2 1.1 haad # Create a temporary directory, sort of like mktemp -d does. 3 1.1 haad 4 1.1 haad # Copyright (C) 2007 Red Hat, Inc. All rights reserved. 5 1.1 haad # 6 1.1 haad # This copyrighted material is made available to anyone wishing to use, 7 1.1 haad # modify, copy, or redistribute it subject to the terms and conditions 8 1.1 haad # of the GNU General Public License v.2. 9 1.1 haad # 10 1.1 haad # You should have received a copy of the GNU General Public License 11 1.1 haad # along with this program; if not, write to the Free Software Foundation, 12 1.1 haad # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13 1.1 haad 14 1.1 haad # Written by Jim Meyering. 15 1.1 haad 16 1.1 haad # Usage: mkdtemp /tmp phoey.XXXXXXXXXX 17 1.1 haad 18 1.1 haad # First, try to use the mktemp program. 19 1.1 haad # Failing that, we'll roll our own mktemp-like function: 20 1.1 haad # - try to get random bytes from /dev/urandom 21 1.1 haad # - failing that, generate output from a combination of quickly-varying 22 1.1 haad # sources and gzip. Ignore non-varying gzip header, and extract 23 1.1 haad # "random" bits from there. 24 1.1 haad # - given those bits, map to file-name bytes using tr, and try to create 25 1.1 haad # the desired directory. 26 1.1 haad # - make only $MAX_TRIES attempts 27 1.1 haad 28 1.1 haad ME=$(basename "$0") 29 1.1 haad die() { echo >&2 "$ME: $@"; exit 1; } 30 1.1 haad 31 1.1 haad MAX_TRIES=4 32 1.1 haad 33 1.1 haad rand_bytes() 34 1.1 haad { 35 1.1 haad n=$1 36 1.1 haad 37 1.1 haad chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 38 1.1 haad 39 1.1 haad dev_rand=/dev/urandom 40 1.1 haad if test -r "$dev_rand"; then 41 1.1 haad # Note: 256-length($chars) == 194; 3 copies of $chars is 186 + 8 = 194. 42 1.1 haad head -c$n "$dev_rand" | tr -c $chars 01234567$chars$chars$chars 43 1.1 haad return 44 1.1 haad fi 45 1.1 haad 46 1.1 haad cmds='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n' 47 1.1 haad data=$( (eval "$cmds") 2>&1 | gzip ) 48 1.1 haad 49 1.1 haad n_plus_50=$(expr $n + 50) 50 1.1 haad 51 1.1 haad # Ensure that $data has length at least 50+$n 52 1.1 haad while :; do 53 1.1 haad len=$(echo "$data"|wc -c) 54 1.1 haad test $n_plus_50 -le $len && break; 55 1.1 haad data=$( (echo "$data"; eval "$cmds") 2>&1 | gzip ) 56 1.1 haad done 57 1.1 haad 58 1.1 haad echo "$data" \ 59 1.1 haad | dd bs=1 skip=50 count=$n 2>/dev/null \ 60 1.1 haad | tr -c $chars 01234567$chars$chars$chars 61 1.1 haad } 62 1.1 haad 63 1.1 haad mkdtemp() 64 1.1 haad { 65 1.1 haad case $# in 66 1.1 haad 2);; 67 1.1 haad *) die "Usage: $ME DIR TEMPLATE";; 68 1.1 haad esac 69 1.1 haad 70 1.1 haad destdir=$1 71 1.1 haad template=$2 72 1.1 haad 73 1.1 haad case $template in 74 1.1 haad *XXXX) ;; 75 1.1 haad *) die "invalid template: $template (must have a suffix of at least 4 X's)";; 76 1.1 haad esac 77 1.1 haad 78 1.1 haad fail=0 79 1.1 haad 80 1.1 haad # First, try to use mktemp. 81 1.1 haad d=$(env -u TMPDIR mktemp -d -t -p "$destdir" "$template" 2>/dev/null) \ 82 1.1 haad || fail=1 83 1.1 haad 84 1.1 haad # The resulting name must be in the specified directory. 85 1.1 haad case $d in "$destdir"*);; *) fail=1;; esac 86 1.1 haad 87 1.1 haad # It must have created the directory. 88 1.1 haad test -d "$d" || fail=1 89 1.1 haad 90 1.1 haad # It must have 0700 permissions. 91 1.1 haad perms=$(ls -dgo "$d" 2>/dev/null) || fail=1 92 1.1 haad case $perms in drwx------*) ;; *) fail=1;; esac 93 1.1 haad 94 1.1 haad test $fail = 0 && { 95 1.1 haad echo "$d" 96 1.1 haad return 97 1.1 haad } 98 1.1 haad 99 1.1 haad # If we reach this point, we'll have to create a directory manually. 100 1.1 haad 101 1.1 haad # Get a copy of the template without its suffix of X's. 102 1.1 haad base_template=$(echo "$template"|sed 's/XX*$//') 103 1.1 haad 104 1.1 haad # Calculate how many X's we've just removed. 105 1.1 haad nx=$(expr length "$template" - length "$base_template") 106 1.1 haad 107 1.1 haad err= 108 1.1 haad i=1 109 1.1 haad while :; do 110 1.1 haad X=$(rand_bytes $nx) 111 1.1 haad candidate_dir="$destdir/$base_template$X" 112 1.1 haad err=$(mkdir -m 0700 "$candidate_dir" 2>&1) \ 113 1.1 haad && { echo "$candidate_dir"; return; } 114 1.1 haad test $MAX_TRIES -le $i && break; 115 1.1 haad i=$(expr $i + 1) 116 1.1 haad done 117 1.1 haad die "$err" 118 1.1 haad } 119 1.1 haad 120 1.1 haad mkdtemp "$@" 121