Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 245 lines (187 sloc) 6.085 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
#!/bin/bash
#
# geninit.api
#
# This file is part of geninit.
#
# declares intended public API calls for builders to use. These functions
# should be used over other functions in geninit such as __add_file, which have
# no awareness of things such as $basedir or $kernver.
#

add_dir() { # {{{
  # add a directory (with parents)
  # $1: absolute path on initcpio
  # $2: mode (optional, defaults to 755)

  (( ! $# )) && return 1 # NOOP

  local path=$1 mode=${2:-755}

  __add_dir "$path" "$mode"
} # }}}

add_file() { # {{{
  # add a regular file. no parsing done.
  # $1: source on disk
  # $2: destination on initcpio (optional: assumes same as source)

  (( $# )) || return 1 # NOOP

  # determine source and destination
  local src= dest=${2:-$1} mode=

  if [[ "${1:0:1}" == @ ]]; then # assert an absolute path
    src=${1:1}
  else
    src=$basedir$1
  fi

  [[ -f "$src" ]] || { error "$src: No such file"; return 1; }

  mode=$(stat -c %a "$src")
  if [[ -z "$mode" ]]; then
    error "failed to stat file: \`$src'"
    return 1
  fi

  __add_file "${dest#$basedir}" "$src" "$mode"
} # }}}

add_symlink() { # {{{
  # add a symlink
  # $1: target of $2
  # $2: name on initcpio

  (( $# == 2 )) || return 1

  add_path_to_file "$1"
  __add_slink "$2" "$1"
} # }}}

add_path_to_file() { # {{{
  # add the path leading up to a file
  # $1: filename with full path

  (( $# )) || return 1

  add_dir "${1%/*}"
} # }}}

add_module() { # {{{
  # add a kernel module with dependencies
  # $1: kernel module by name (no path, with or without extension)

  (( $# )) || return 1

  local -a deps
  local modpath= module= mod= dep= field= value=

  module=${1%%.*}

  while IFS=':= ' read -r -d '' field value; do
    case "$field" in
      filename)
        modpath=$value
        ;;
      depends)
        IFS=',' read -r -a deps <<< "$value"
        for dep in "${deps[@]}"; do
          add_module "$dep"
        done
        ;;
      firmware)
        if [[ -e "$basedir/lib/firmware/$value" ]]; then
          __add_file "/lib/firmware/$value" "$basedir/lib/firmware/$value"
        fi
        ;;
    esac
  done < <(modinfo "$module" -b "$basedir" -0k $kernver 2>/dev/null)

  if [[ -z $modpath ]]; then
    error "Module not found: $module"
    return 1
  fi

  __add_file "${modpath#$basedir}" "$modpath" 644
  [[ $? = @(0|$EEXIST) ]] || return 1

  # add in any quirks
  for mod in ${modquirks[$module]}; do
    add_module "$mod"
  done

  return 0
} # }}}

add_binary() { # {{{
  # add a binary file with .so depends
  # $1: path to binary
  # $2: destination on initcpio (optional: assumes same as source)

  (( $# )) || return 1

  local -a sodeps
  local regex= binary= dest= mode= sodep= resolved= dirname=

  if [[ "${1:0:1}" == @ ]]; then # assert an absolute path
    binary=${1:1}
  else
    binary=$basedir$1
  fi

  [[ -f "$binary" ]] || { error "$binary not found"; return 1; }

  dest=${2:-$binary}
  mode=$(stat -c %a "$binary")

  # the file itself
  __add_file "$dest" "$binary" "$mode"

  "$ld_so" --verify "$binary" &>/dev/null || return # not a binary!

  # resolve sodeps
  regex='^[[:space:]]*[^/].+ => (.*) \(.*\)'
  while read line; do
    [[ "$line" =~ $regex ]] && sodep="${BASH_REMATCH[1]}" || continue

    if [[ -f "$sodep" ]]; then # -f follows symlinks, don't believe it!
      if [[ ! -L $sodep ]]; then
        __add_file "$sodep" "$basedir$sodep" "$(stat -c %a "$sodep")"
      else
        resolved=$(readlink -e "$basedir$sodep")
        dirname=${resolved%/*}
        __add_dir "${dirname#$basedir}" 755
        __add_slink "$sodep" "${resolved#$basedir}"
        __add_file "${resolved#$basedir}" "$resolved" 755
      fi
    fi
  done < <(__ldd "$binary")

} # }}}

add_pipe() { # {{{
  # add a fifo
  # $1: path of pipe
  # $2: mode (optional, defaults to 644)

  (( $# )) || return 1

  add_path_to_file "$1"
  __add_pipe "$1" "${2:-644}"
} # }}}

use_hookscript() { # {{{
  # specifies that a builder should install a hookscript
  # "$builder" comes from the builder parsing loop in main
  # $1: script name (optional, defaults to the name of the builder)
  local script=${1:-$builder}

  if [[ ! -f $basedir$_sharedir/hooks/$script ]]; then
    error "unable to find hook script: $script"
    return 1
  fi

  __add_file "/hooks/$script" "$basedir$_sharedir/hooks/$script" 755
} # }}}

use_mounthook() { # {{{
  # specifies that a builder should install a custom mount handler.

  local mounthook=${1:-$builder}

  if [[ ! -f $basedir$_sharedir/mount/$mounthook ]]; then
    error "unable to find mount hook: $mounthook"
    return 1
  fi

  __add_file "/mount/$mounthook" "$basedir$_sharedir/mount/$mounthook" 755
} # }}}

add_checked_modules() { # {{{
  # add a class of modules, as a dir relative to /lib/modules/$kernver/kernel.
  # if you need to block addition of modules, you can add glob patterns to the
  # 'MODFILTER' array within your builder. They must be quoted and the
  # filter is cleared after parsing of each builder.
  # $@: directories

  local -a mods
  local -i ret=0
  local mod=

  # find modules by class (e.g. drivers/ata)
  pushd "$basedir$moduledir/kernel" &>/dev/null
  while read -rd '' mod; do
    mods+=("${mod%%.*}")
  done < <(find "$@" -type f -name '*.ko*' -printf '%f\0' 2>/dev/null)
  popd &>/dev/null

  # only add what autodetect found if we have a module cache
  [[ -s "$autodetect_cache" && -z "$NOAUTO" ]] &&
    IFS=$'\n' read -rd '' -a mods < <(grep -xFf <(printf '%s\n' "${mods[@]//-/_}") "$autodetect_cache")

  for mod in "${mods[@]}"; do
    # check for filter match
    for filter in "${MODFILTER[@]}"; do
      [[ "$mod" == $filter ]] && continue 2
    done

    add_module "$mod" && (( ++ret ))
  done

  # return 0 on modules added, else 1
  return $(( ! ret ))
} # }}}

add_all_modules() { # {{{
  # add a class of modules, as a dir relative to /lib/modules/$kernver/kernel.
  # this function honors 'MODFILTER', but does not check against the autodetected
  # cache of modules.

  NOAUTO=1 add_checked_modules "$@"
} # }}}

# vim: set et sw=2 ft=sh:
Something went wrong with that request. Please try again.