ipkg-build 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #!/bin/sh
  2. # ipkg-build -- construct a .ipk from a directory
  3. # Carl Worth <[email protected]>
  4. # based on a script by Steve Redler IV, [email protected] 5-21-2001
  5. # 2003-04-25 [email protected]
  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. mv "$CONTROL"/conffiles.resolved "$CONTROL"/conffiles
  49. chmod 0644 "$CONTROL"/conffiles
  50. fi
  51. fi
  52. cd "$owd"
  53. return $PKG_ERROR
  54. }
  55. resolve_file_mode_id() {
  56. local var=$1 type=$2 name=$3 id
  57. case "$name" in
  58. root)
  59. id=0
  60. ;;
  61. *[!0-9]*)
  62. id=$(sed -ne "s#^$type $name \\([0-9]\\+\\)\\b.*\$#\\1#p" "$TOPDIR/tmp/.packageusergroup" 2>/dev/null)
  63. ;;
  64. *)
  65. id=$name
  66. ;;
  67. esac
  68. export "$var=$id"
  69. [ -n "$id" ]
  70. }
  71. ###
  72. # ipkg-build "main"
  73. ###
  74. file_modes=""
  75. usage="Usage: $0 [-v] [-h] [-m] <pkg_directory> [<destination_directory>]"
  76. while getopts "hvm:" opt; do
  77. case $opt in
  78. v ) echo "$version"
  79. exit 0
  80. ;;
  81. h ) echo "$usage" >&2 ;;
  82. m ) file_modes=$OPTARG ;;
  83. \? ) echo "$usage" >&2
  84. esac
  85. done
  86. shift $((OPTIND - 1))
  87. # continue on to process additional arguments
  88. case $# in
  89. 1)
  90. dest_dir=$PWD
  91. ;;
  92. 2)
  93. dest_dir=$2
  94. if [ "$dest_dir" = "." ] || [ "$dest_dir" = "./" ] ; then
  95. dest_dir=$PWD
  96. fi
  97. ;;
  98. *)
  99. echo "$usage" >&2
  100. exit 1
  101. ;;
  102. esac
  103. pkg_dir="$(realpath "$1")"
  104. if [ ! -d "$pkg_dir" ]; then
  105. echo "*** Error: Directory $pkg_dir does not exist" >&2
  106. exit 1
  107. fi
  108. # CONTROL is second so that it takes precedence
  109. CONTROL=
  110. [ -d "$pkg_dir"/CONTROL ] && CONTROL=CONTROL
  111. if [ -z "$CONTROL" ]; then
  112. echo "*** Error: Directory $pkg_dir has no CONTROL subdirectory." >&2
  113. exit 1
  114. fi
  115. if ! pkg_appears_sane "$pkg_dir"; then
  116. echo >&2
  117. echo "ipkg-build: Please fix the above errors and try again." >&2
  118. exit 1
  119. fi
  120. tmp_dir=$dest_dir/IPKG_BUILD.$$
  121. mkdir "$tmp_dir"
  122. echo $CONTROL > "$tmp_dir"/tarX
  123. cd "$pkg_dir"
  124. for file_mode in $file_modes; do
  125. case $file_mode in
  126. /*:*:*:*)
  127. ;;
  128. *)
  129. echo "ERROR: file modes must use absolute path and contain user:group:mode"
  130. echo "$file_mode"
  131. exit 1
  132. ;;
  133. esac
  134. mode=${file_mode##*:}; path=${file_mode%:*}
  135. group=${path##*:}; path=${path%:*}
  136. user=${path##*:}; path=${path%:*}
  137. if ! resolve_file_mode_id uid user "$user"; then
  138. echo "ERROR: unable to resolve uid of $user" >&2
  139. exit 1
  140. fi
  141. if ! resolve_file_mode_id gid group "$group"; then
  142. echo "ERROR: unable to resolve gid of $group" >&2
  143. exit 1
  144. fi
  145. chown "$uid:$gid" "$pkg_dir/$path"
  146. chmod "$mode" "$pkg_dir/$path"
  147. done
  148. $TAR -X "$tmp_dir"/tarX --format=gnu --sort=name -cpf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/data.tar.gz
  149. installed_size=$(stat -c "%s" "$tmp_dir"/data.tar.gz)
  150. sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \
  151. "$pkg_dir"/$CONTROL/control
  152. ( cd "$pkg_dir"/$CONTROL && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/control.tar.gz )
  153. rm "$tmp_dir"/tarX
  154. echo "2.0" > "$tmp_dir"/debian-binary
  155. pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk
  156. rm -f "$pkg_file"
  157. ( cd "$tmp_dir" && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" ./debian-binary ./data.tar.gz ./control.tar.gz | gzip -n - > "$pkg_file" )
  158. rm "$tmp_dir"/debian-binary "$tmp_dir"/data.tar.gz "$tmp_dir"/control.tar.gz
  159. rmdir "$tmp_dir"
  160. echo "Packaged contents of $pkg_dir into $pkg_file"