ipkg-build 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/bin/sh
  2. # ipkg-build -- construct a .ipk from a directory
  3. # Carl Worth <cworth@east.isi.edu>
  4. # based on a script by Steve Redler IV, steve@sr-tech.com 5-21-2001
  5. # 2003-04-25 rea@sr.unh.edu
  6. # Updated to work on Familiar Pre0.7rc1, with busybox tar.
  7. # Note it Requires: binutils-ar (since the busybox ar can't create)
  8. # For UID debugging it needs a better "find".
  9. set -e
  10. version=1.0
  11. FIND="$(command -v find)"
  12. FIND="${FIND:-$(command -v gfind)}"
  13. TAR="${TAR:-$(command -v tar)}"
  14. # try to use fixed source epoch
  15. if [ -n "$PKG_SOURCE_DATE_EPOCH" ]; then
  16. TIMESTAMP=$(date --date="@$PKG_SOURCE_DATE_EPOCH")
  17. elif [ -n "$SOURCE_DATE_EPOCH" ]; then
  18. TIMESTAMP=$(date --date="@$SOURCE_DATE_EPOCH")
  19. else
  20. TIMESTAMP=$(date)
  21. fi
  22. ipkg_extract_value() {
  23. sed -e "s/^[^:]*:[[:space:]]*//"
  24. }
  25. required_field() {
  26. field=$1
  27. grep "^$field:" < "$CONTROL/control" | ipkg_extract_value
  28. }
  29. pkg_appears_sane() {
  30. local pkg_dir="$1"
  31. local owd="$PWD"
  32. cd "$pkg_dir"
  33. PKG_ERROR=0
  34. pkg="$(required_field Package)"
  35. version="$(required_field Version | sed 's/Version://; s/^.://g;')"
  36. arch="$(required_field Architecture)"
  37. if echo "$pkg" | grep '[^a-zA-Z0-9_.+-]'; then
  38. echo "*** Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])" >&2
  39. PKG_ERROR=1;
  40. fi
  41. if [ -f "$CONTROL/conffiles" ]; then
  42. rm -f "$CONTROL/conffiles.resolved"
  43. for cf in $($FIND $(sed -e "s!^/!$pkg_dir/!" "$CONTROL/conffiles") -type f); do
  44. echo "${cf#$pkg_dir}" >> "$CONTROL/conffiles.resolved"
  45. done
  46. rm "$CONTROL"/conffiles
  47. if [ -f "$CONTROL"/conffiles.resolved ]; then
  48. LC_ALL=C sort -o "$CONTROL"/conffiles "$CONTROL"/conffiles.resolved
  49. rm "$CONTROL"/conffiles.resolved
  50. chmod 0644 "$CONTROL"/conffiles
  51. fi
  52. fi
  53. cd "$owd"
  54. return $PKG_ERROR
  55. }
  56. resolve_file_mode_id() {
  57. local var=$1 type=$2 name=$3 id
  58. case "$name" in
  59. root)
  60. id=0
  61. ;;
  62. *[!0-9]*)
  63. id=$(sed -ne "s#^$type $name \\([0-9]\\+\\)\\b.*\$#\\1#p" "$TOPDIR/tmp/.packageusergroup" 2>/dev/null)
  64. ;;
  65. *)
  66. id=$name
  67. ;;
  68. esac
  69. export "$var=$id"
  70. [ -n "$id" ]
  71. }
  72. ###
  73. # ipkg-build "main"
  74. ###
  75. file_modes=""
  76. usage="Usage: $0 [-v] [-h] [-m] <pkg_directory> [<destination_directory>]"
  77. while getopts "hvm:" opt; do
  78. case $opt in
  79. v ) echo "$version"
  80. exit 0
  81. ;;
  82. h ) echo "$usage" >&2 ;;
  83. m ) file_modes=$OPTARG ;;
  84. \? ) echo "$usage" >&2
  85. esac
  86. done
  87. shift $((OPTIND - 1))
  88. # continue on to process additional arguments
  89. case $# in
  90. 1)
  91. dest_dir=$PWD
  92. ;;
  93. 2)
  94. dest_dir=$2
  95. if [ "$dest_dir" = "." ] || [ "$dest_dir" = "./" ] ; then
  96. dest_dir=$PWD
  97. fi
  98. ;;
  99. *)
  100. echo "$usage" >&2
  101. exit 1
  102. ;;
  103. esac
  104. pkg_dir="$(realpath "$1")"
  105. if [ ! -d "$pkg_dir" ]; then
  106. echo "*** Error: Directory $pkg_dir does not exist" >&2
  107. exit 1
  108. fi
  109. # CONTROL is second so that it takes precedence
  110. CONTROL=
  111. [ -d "$pkg_dir"/CONTROL ] && CONTROL=CONTROL
  112. if [ -z "$CONTROL" ]; then
  113. echo "*** Error: Directory $pkg_dir has no CONTROL subdirectory." >&2
  114. exit 1
  115. fi
  116. if ! pkg_appears_sane "$pkg_dir"; then
  117. echo >&2
  118. echo "ipkg-build: Please fix the above errors and try again." >&2
  119. exit 1
  120. fi
  121. tmp_dir=$dest_dir/IPKG_BUILD.$$
  122. mkdir "$tmp_dir"
  123. echo $CONTROL > "$tmp_dir"/tarX
  124. cd "$pkg_dir"
  125. for file_mode in $file_modes; do
  126. case $file_mode in
  127. /*:*:*:*)
  128. ;;
  129. *)
  130. echo "ERROR: file modes must use absolute path and contain user:group:mode"
  131. echo "$file_mode"
  132. exit 1
  133. ;;
  134. esac
  135. mode=${file_mode##*:}; path=${file_mode%:*}
  136. group=${path##*:}; path=${path%:*}
  137. user=${path##*:}; path=${path%:*}
  138. if ! resolve_file_mode_id uid user "$user"; then
  139. echo "ERROR: unable to resolve uid of $user" >&2
  140. exit 1
  141. fi
  142. if ! resolve_file_mode_id gid group "$group"; then
  143. echo "ERROR: unable to resolve gid of $group" >&2
  144. exit 1
  145. fi
  146. chown "$uid:$gid" "$pkg_dir/$path"
  147. chmod "$mode" "$pkg_dir/$path"
  148. done
  149. $TAR -X "$tmp_dir"/tarX --format=gnu --numeric-owner --sort=name -cpf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/data.tar.gz
  150. installed_size=$(stat -c "%s" "$tmp_dir"/data.tar.gz)
  151. sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \
  152. "$pkg_dir"/$CONTROL/control
  153. ( cd "$pkg_dir"/$CONTROL && $TAR --format=gnu --numeric-owner --sort=name -cf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/control.tar.gz )
  154. rm "$tmp_dir"/tarX
  155. echo "2.0" > "$tmp_dir"/debian-binary
  156. pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk
  157. rm -f "$pkg_file"
  158. ( cd "$tmp_dir" && $TAR --format=gnu --numeric-owner --sort=name -cf - --mtime="$TIMESTAMP" ./debian-binary ./data.tar.gz ./control.tar.gz | gzip -n - > "$pkg_file" )
  159. rm "$tmp_dir"/debian-binary "$tmp_dir"/data.tar.gz "$tmp_dir"/control.tar.gz
  160. rmdir "$tmp_dir"
  161. echo "Packaged contents of $pkg_dir into $pkg_file"