... | ... |
@@ -2,8 +2,8 @@ from CommandUtils import CommandUtils |
2 | 2 |
from ChrootUtils import ChrootUtils |
3 | 3 |
from Logger import Logger |
4 | 4 |
from PackageUtils import PackageUtils |
5 |
-import shutil |
|
6 | 5 |
from constants import constants |
6 |
+import subprocess |
|
7 | 7 |
|
8 | 8 |
class ToolChainUtils(object): |
9 | 9 |
__built_successfull=False |
... | ... |
@@ -21,41 +21,69 @@ class ToolChainUtils(object): |
21 | 21 |
self.localegenConfig = "./locale-gen.conf" |
22 | 22 |
self.prepareBuildRootCmd="./prepare-build-root.sh" |
23 | 23 |
|
24 |
- def prepareChroot(self,chrootID,toolsArchive=None): |
|
24 |
+ #Tool chain should be built before calling this method |
|
25 |
+ def installToolChain(self,chrootID): |
|
26 |
+ self.logger.info("Installing toolchain.....") |
|
27 |
+ self.installCoreToolChainPackages(chrootID) |
|
28 |
+ self.logger.info("Installed tool chain successfully on chroot:"+chrootID) |
|
29 |
+ |
|
30 |
+ def installCoreToolChainPackages(self,chrootID): |
|
31 |
+ self.logger.info("Installing toolchain.....") |
|
32 |
+ self.prepareBuildEnvironmentChroot(chrootID) |
|
25 | 33 |
cmdUtils=CommandUtils() |
26 |
- prepareChrootCmd=self.prepareBuildRootCmd+" "+chrootID+" "+constants.specPath+" "+constants.rpmPath+" "+constants.toolsPath |
|
27 |
- if toolsArchive is not None: |
|
28 |
- prepareChrootCmd=prepareChrootCmd+" "+toolsArchive |
|
29 |
- returnVal=cmdUtils.runCommandInShell(prepareChrootCmd) |
|
30 |
- if not returnVal: |
|
31 |
- self.logger.error("Prepare build root script failed.Unable to prepare chroot.") |
|
32 |
- raise Exception("Prepare build root script failed") |
|
33 |
- |
|
34 |
- cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS") |
|
35 |
- cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS/x86_64") |
|
36 |
- cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS/noarch") |
|
37 |
- cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/SOURCES") |
|
38 |
- cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/SPECS") |
|
39 |
- self.logger.info("Successfully prepared chroot:"+chrootID) |
|
34 |
+ cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/x86_64/*") |
|
35 |
+ cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/noarch/*") |
|
36 |
+ self.logger.info("Installed core tool chain packages successfully on chroot:"+chrootID) |
|
37 |
+ |
|
38 |
+ listToolChainRPMPkgs=["linux-api-headers", "glibc","glibc-devel", "zlib","zlib-devel", "file", |
|
39 |
+ "binutils","binutils-devel", "gmp","gmp-devel", "mpfr", "mpfr-devel", "mpc", |
|
40 |
+ "libgcc","libgcc-devel","libstdc++","libstdc++-devel","libgomp","libgomp-devel","gcc", |
|
41 |
+ "pkg-config", "ncurses", "bash", "bzip2", "sed","ncurses-devel","procps-ng","coreutils", "m4","grep", |
|
42 |
+ "readline", "diffutils","gawk", "findutils", "gettext", "gzip","make", "patch", |
|
43 |
+ "util-linux", "tar", "xz","libtool", "flex", "bison", |
|
44 |
+ "readline-devel", "lua","lua-devel","popt","popt-devel","nspr","sqlite-autoconf","nss","nss-devel", |
|
45 |
+ "bzip2-devel","elfutils-libelf","elfutils","elfutils-libelf-devel","elfutils-devel", |
|
46 |
+ "expat","libffi","libpipeline", "gdbm","perl","texinfo","autoconf","automake", |
|
47 |
+ "openssl","openssl-devel","python2","python2-libs","python2-devel","rpm", |
|
48 |
+ "groff", "man-db", "man-pages","cpio"] |
|
49 |
+ |
|
50 |
+ def findRPMFileInGivenLocation(self,package,rpmdirPath): |
|
51 |
+ cmdUtils = CommandUtils() |
|
52 |
+ listFoundRPMFiles = cmdUtils.findFile(package+"-*.rpm",rpmdirPath) |
|
53 |
+ listFilterRPMFiles=[] |
|
54 |
+ for f in listFoundRPMFiles: |
|
55 |
+ f1=f.replace(package,"") |
|
56 |
+ print f1 |
|
57 |
+ l = f1.split("-") |
|
58 |
+ print l |
|
59 |
+ if len(l) == 3: |
|
60 |
+ listFilterRPMFiles.append(f) |
|
61 |
+ if len(listFilterRPMFiles) == 1 : |
|
62 |
+ return listFilterRPMFiles[0] |
|
63 |
+ if len(listFilterRPMFiles) == 0 : |
|
64 |
+ return None |
|
65 |
+ if len(listFilterRPMFiles) > 1 : |
|
66 |
+ print("Found multiple rpm files for given package in rpm directory.Unable to determine the rpm file for package:"+package) |
|
67 |
+ return None |
|
40 | 68 |
|
41 | 69 |
def buildCoreToolChainPackages(self): |
42 | 70 |
self.logger.info("Building core tool chain packages.....") |
43 | 71 |
chrootID=None |
44 |
- chrUtils = ChrootUtils(self.logName,self.logPath) |
|
45 | 72 |
try: |
46 |
- chrootName="build-core-toolchain" |
|
47 |
- returnVal,chrootID = chrUtils.createChroot(chrootName) |
|
48 |
- if not returnVal: |
|
49 |
- raise Exception("creating chroot failed") |
|
50 |
- self.prepareChroot(chrootID) |
|
51 | 73 |
pkgUtils=PackageUtils(self.logName,self.logPath) |
52 | 74 |
for package in constants.listCoreToolChainRPMPackages: |
75 |
+ chrUtils = ChrootUtils(self.logName,self.logPath) |
|
76 |
+ chrootName="build-core-toolchain" |
|
77 |
+ returnVal,chrootID = chrUtils.createChroot(chrootName) |
|
78 |
+ if not returnVal: |
|
79 |
+ self.logger.error("Creating chroot failed") |
|
80 |
+ raise Exception("creating chroot failed") |
|
81 |
+ self.prepareBuildEnvironmentChroot(chrootID) |
|
53 | 82 |
rpmPkg=pkgUtils.findRPMFileForGivenPackage(package) |
54 | 83 |
if rpmPkg is None: |
55 | 84 |
pkgUtils.buildRPMSForGivenPackage(package, chrootID) |
56 |
- pkgUtils.installRPM(package, chrootID, True) |
|
57 |
- if package == "glibc": |
|
58 |
- self.adjustToolChain(chrootID) |
|
85 |
+ chrUtils.destroyChroot(chrootID) |
|
86 |
+ chrootID=None |
|
59 | 87 |
self.logger.info("Successfully built toolchain") |
60 | 88 |
except Exception as e: |
61 | 89 |
self.logger.error("Unable to build tool chain.") |
... | ... |
@@ -63,58 +91,38 @@ class ToolChainUtils(object): |
63 | 63 |
finally: |
64 | 64 |
if chrootID is not None: |
65 | 65 |
chrUtils.destroyChroot(chrootID) |
66 |
- |
|
67 |
- #Tool chain should be built before calling this method |
|
68 |
- def installToolChain(self,chrootID): |
|
69 |
- self.logger.info("Installing toolchain.....") |
|
70 |
- self.prepareChroot(chrootID,"minimal") |
|
71 |
- pkgUtils= PackageUtils(self.logName,self.logPath) |
|
72 |
- for package in constants.listToolChainRPMPkgs: |
|
73 |
- pkgUtils.installRPM(package, chrootID, True) |
|
74 |
- cmdUtils=CommandUtils() |
|
75 |
- cmdUtils.runCommandInShell("rm -rf "+ chrootID+"/tools") |
|
76 |
- cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/x86_64/*") |
|
77 |
- cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/noarch/*") |
|
78 |
- self.logger.info("Installed tool chain successfully on chroot:"+chrootID) |
|
79 |
- |
|
80 |
- def adjustToolChain(self,chrootID): |
|
81 |
- shutil.copy2(self.adjustToolChainScript, chrootID+"/tmp") |
|
82 |
- shutil.copy2(self.localegenScript, chrootID+"/sbin") |
|
83 |
- shutil.copy2(self.localegenConfig, chrootID+"/etc") |
|
84 |
- cmdUtils=CommandUtils() |
|
85 |
- logFile=constants.logPath+"/adjustToolChainScript.log" |
|
86 |
- returnVal = cmdUtils.runCommandInShell("/tmp/"+self.adjustToolChainScript,logFile, "./run-in-chroot.sh "+chrootID) |
|
66 |
+ |
|
67 |
+ def prepareBuildEnvironmentChroot(self,chrootID): |
|
68 |
+ self.logger.info("Preparing build environment") |
|
69 |
+ previousVersionRPMSPath="/workspace1/testTP1RPMS/RPMS" |
|
70 |
+ cmdUtils = CommandUtils() |
|
71 |
+ prepareChrootCmd=self.prepareBuildRootCmd+" "+chrootID+" "+constants.specPath+" "+constants.rpmPath+" "+constants.logPath |
|
72 |
+ logFile=constants.logPath+"/prepareBuildRoot.log" |
|
73 |
+ returnVal=cmdUtils.runCommandInShell(prepareChrootCmd,logFile) |
|
87 | 74 |
if not returnVal: |
88 |
- self.logger.error("Adjust tool chain script failed.") |
|
89 |
- raise Exception("Adjust tool chain script failed") |
|
90 |
- |
|
91 |
- |
|
92 |
- def installCoreToolChainPackages(self,chrootID): |
|
93 |
- self.logger.info("Installing toolchain.....") |
|
94 |
- self.prepareChroot(chrootID) |
|
95 |
- pkgUtils= PackageUtils(self.logName,self.logPath) |
|
96 |
- for package in constants.listCoreToolChainRPMPackages: |
|
97 |
- pkgUtils.installRPM(package, chrootID, True) |
|
98 |
- if package == "glibc": |
|
99 |
- self.adjustToolChain(chrootID) |
|
100 |
- cmdUtils=CommandUtils() |
|
101 |
- cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/x86_64/*") |
|
102 |
- cmdUtils.runCommandInShell("rm "+ chrootID+"/"+constants.topDirPath+"/RPMS/noarch/*") |
|
103 |
- self.logger.info("Installed core tool chain packages successfully on chroot:"+chrootID) |
|
104 |
- |
|
105 |
- |
|
106 |
- |
|
107 |
- |
|
108 |
- |
|
109 |
- |
|
110 |
- |
|
111 |
- |
|
112 |
- |
|
113 |
- |
|
114 |
- |
|
115 |
- |
|
75 |
+ self.logger.error("Prepare build root script failed.Unable to prepare chroot.") |
|
76 |
+ raise Exception("Prepare build root script failed") |
|
116 | 77 |
|
78 |
+ for package in ToolChainUtils.listToolChainRPMPkgs: |
|
79 |
+ pkgUtils=PackageUtils(self.logName,self.logPath) |
|
80 |
+ rpmFile=pkgUtils.findRPMFileForGivenPackage(package) |
|
81 |
+ if rpmFile is None: |
|
82 |
+ rpmFile=self.findRPMFileInGivenLocation(package, previousVersionRPMSPath) |
|
83 |
+ if rpmFile is None: |
|
84 |
+ self.logger.error("Unable to find rpm "+ package +" in current and previous versions") |
|
85 |
+ raise "Input Error" |
|
86 |
+ self.logger.debug("Installing rpm:"+rpmFile) |
|
87 |
+ cmd="rpm -i --nodeps --root "+chrootID+" --define \'_dbpath /var/lib/rpm\' "+ rpmFile |
|
88 |
+ process = subprocess.Popen("%s" %cmd,shell=True,stdout=subprocess.PIPE) |
|
89 |
+ retval = process.wait() |
|
90 |
+ if retval != 0: |
|
91 |
+ self.logger.error("Installing tool chain package "+package+" failed") |
|
92 |
+ raise "RPM installation failed" |
|
117 | 93 |
|
118 |
- |
|
119 |
- |
|
120 |
- |
|
94 |
+ cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS") |
|
95 |
+ cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS/x86_64") |
|
96 |
+ cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/RPMS/noarch") |
|
97 |
+ cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/SOURCES") |
|
98 |
+ cmdUtils.runCommandInShell("mkdir -p "+chrootID+constants.topDirPath+"/SPECS") |
|
99 |
+ self.logger.info("Successfully prepared chroot:"+chrootID) |
|
100 |
+ |
|
121 | 101 |
\ No newline at end of file |
... | ... |
@@ -43,10 +43,6 @@ def main(): |
43 | 43 |
logger.info("Log Path :" + options.logPath) |
44 | 44 |
logger.info("Top Dir Path :" + options.topDirPath) |
45 | 45 |
|
46 |
- if not os.path.isfile(options.toolsPath+"/tools-build.tar"): |
|
47 |
- logger.error("Missing tools-build tar from tools path"+options.toolsPath) |
|
48 |
- logger.error("Please provide correct tools path and continue") |
|
49 |
- return False |
|
50 | 46 |
|
51 | 47 |
listPackages=["acl","attr","autoconf","automake","bash","bc","bindutils","binutils","bison","boost","btrfs-progs","bzip2","ca-certificates","cdrkit","check", |
52 | 48 |
"cloud-init","cmake","coreutils","cpio","cracklib","createrepo","curl","cyrus-sasl","db","dbus","deltarpm","diffutils","docbook-xml","docbook-xsl", |
... | ... |
@@ -10,53 +10,27 @@ set -o nounset |
10 | 10 |
set +h |
11 | 11 |
source common.inc |
12 | 12 |
|
13 |
-LOGFILE="$(date +%Y-%m-%d).log" |
|
14 |
-LOG_PATH=../../stage/LOGS |
|
15 | 13 |
PRGNAME=${0##*/} |
16 |
-LOGFILE=$LOG_PATH/"${PRGNAME}-${LOGFILE}" |
|
14 |
+ |
|
17 | 15 |
if [ $# -lt 4 ]; then |
18 |
- fail "${PRGNAME}: No build root specified. Usage : ${PRGNAME} <build-root> <spec-path> <rpm-path> <tools-path>" |
|
16 |
+ fail "${PRGNAME}: No build root specified. Usage : ${PRGNAME} <build-root> <spec-path> <rpm-path> <log-path>" |
|
19 | 17 |
fi |
20 | 18 |
|
21 | 19 |
#Clean up our build root first |
22 | 20 |
BUILDROOT=$1 |
23 | 21 |
SPEC_PATH=$2 |
24 | 22 |
RPM_PATH=$3 |
25 |
-TOOLS_PATH=$4 |
|
26 |
-TOOLS_ARCHIVE="" |
|
27 |
-if [ $# -ge 5 ]; then |
|
28 |
- TOOLS_ARCHIVE=$5 |
|
29 |
-fi |
|
23 |
+LOG_PATH=$4 |
|
30 | 24 |
PARENT=/usr/src/photon |
31 |
-rm -rf ${BUILDROOT}/* |
|
32 |
- |
|
33 |
-#LOGFILE=/dev/null # uncomment to disable log file |
|
34 |
-[ ${EUID} -eq 0 ] || fail "${PRGNAME}: Need to be root user: FAILURE" |
|
35 |
-[ -z ${PARENT} ] && fail "${PRGNAME}: PARENT not set: FAILURE" |
|
36 | 25 |
|
37 |
-if [ ! -d ${BUILDROOT} ] ; then |
|
38 |
- echo "Creating directory: ${BUILDROOT}" |
|
39 |
- mkdir -p ${BUILDROOT} |
|
40 |
-fi |
|
26 |
+LOGFILE="$(date +%Y-%m-%d).log" |
|
27 |
+LOGFILE=$LOG_PATH/"${PRGNAME}-${LOGFILE}" |
|
41 | 28 |
|
42 | 29 |
if mountpoint ${BUILDROOT}/run >/dev/null 2>&1; then umount ${BUILDROOT}/run; fi |
43 | 30 |
if mountpoint ${BUILDROOT}/sys >/dev/null 2>&1; then umount ${BUILDROOT}/sys; fi |
44 | 31 |
if mountpoint ${BUILDROOT}/proc >/dev/null 2>&1; then umount ${BUILDROOT}/proc; fi |
45 | 32 |
if mountpoint ${BUILDROOT}/dev/pts >/dev/null 2>&1; then umount ${BUILDROOT}/dev/pts; fi |
46 | 33 |
if mountpoint ${BUILDROOT}/dev >/dev/null 2>&1; then umount ${BUILDROOT}/dev; fi |
47 |
-[ ${EUID} -eq 0 ] || fail "${PRGNAME}: Need to be root user: FAILURE" |
|
48 |
- |
|
49 |
-# |
|
50 |
-#Untar tools build to buildroot |
|
51 |
-# |
|
52 |
- |
|
53 |
-if [ "x$TOOLS_ARCHIVE" = "xminimal" ] ; then |
|
54 |
- echo "Uncompressing the tools tar (minimal)" |
|
55 |
- tar -C ${BUILDROOT} -xzf $TOOLS_PATH/tools.tar.gz >/dev/null |
|
56 |
-else |
|
57 |
- echo "Uncompressing the tools tar" |
|
58 |
- tar -C ${BUILDROOT} -xf $TOOLS_PATH/tools-build.tar >/dev/null |
|
59 |
-fi |
|
60 | 34 |
|
61 | 35 |
mkdir -p ${BUILDROOT}/tmp |
62 | 36 |
mkdir -p ${BUILDROOT}${PARENT} |
... | ... |
@@ -66,40 +40,28 @@ mkdir -p ${BUILDROOT}${PARENT}/BUILDROOT |
66 | 66 |
mkdir -p ${BUILDROOT}${PARENT}/LOGS |
67 | 67 |
mkdir -p ${BUILDROOT}${PARENT}/SOURCES |
68 | 68 |
mkdir -p ${BUILDROOT}${PARENT}/SPECS |
69 |
+ |
|
69 | 70 |
#copy localegen files. |
70 | 71 |
cp ./locale* ${BUILDROOT}${PARENT}/ |
71 | 72 |
#copy kernel config files |
72 | 73 |
cp ./config* ${BUILDROOT}${PARENT}/ |
73 | 74 |
|
74 |
- |
|
75 |
- |
|
76 | 75 |
#copy our macros and set the processor count |
77 |
-NUMPROCS=`nproc` |
|
78 |
-let NUMPROCS=$NUMPROCS+1 |
|
79 |
-echo "%_smp_mflags -j${NUMPROCS}" >> ${BUILDROOT}/tools/etc/rpm/macros |
|
80 |
- |
|
76 |
+#NUMPROCS=`nproc` |
|
77 |
+#let NUMPROCS=$NUMPROCS+1 |
|
78 |
+#echo "%_smp_mflags -j${NUMPROCS}" >> ${BUILDROOT}/tools/etc/rpm/macros |
|
81 | 79 |
|
82 | 80 |
# Setup the filesystem for chapter 06 |
83 | 81 |
RPMPKG="$(find $RPM_PATH -name 'filesystem*.rpm' -print)" |
84 | 82 |
if [ -z ${RPMPKG} ] ; then |
85 | 83 |
run_command " Extracting filesystem spec" "cp ${SPEC_PATH}/filesystem/filesystem.spec ${BUILDROOT}/${PARENT}/SPECS" "$LOG_PATH/filesystem.log" |
86 |
-# rpmbuild requires /bin/bash |
|
87 |
-run_command " Creating symlink: /tools/bin /bin" "ln -fsv /tools/bin ${BUILDROOT}/bin" "$LOG_PATH/filesystem.completed" |
|
88 |
-run_command " Building filesystem rpm (in chroot)" "./run-in-chroot.sh ${BUILDROOT} rpmbuild -ba --nocheck --define \\\"_topdir ${PARENT}\\\" ${PARENT}/SPECS/filesystem.spec" "$LOG_PATH/filesystem.log" |
|
89 |
-run_command " Removing symlink: /tools/bin /bin" "rm -f ${BUILDROOT}/bin" "$LOG_PATH/filesystem.completed" |
|
84 |
+run_command " Building filesystem rpm " "rpmbuild -ba --nocheck --root ${BUILDROOT} --define \\\"_topdir ${PARENT}\\\" ${PARENT}/SPECS/filesystem.spec" "$LOG_PATH/filesystem.log" |
|
90 | 85 |
run_command " Extracting filesystem rpm" "cp ${BUILDROOT}/${PARENT}/RPMS/x86_64/filesystem*.rpm ${RPM_PATH}/x86_64/" "$LOG_PATH/filesystem.log" |
91 | 86 |
fi |
92 | 87 |
RPMPKGFILE="$(find ${RPM_PATH} -name 'filesystem*.rpm' -printf %f)" |
93 | 88 |
[ -z ${RPMPKGFILE} ] && fail " Filesystem rpm package missing: Can not continue" |
94 |
-run_command " Copying filesystem rpm" "cp ${RPM_PATH}/x86_64/${RPMPKGFILE} ${BUILDROOT}/${PARENT}/RPMS/x86_64" "$LOG_PATH/filesystem.log" |
|
95 |
-run_command " Installing filesystem (in chroot)" "./run-in-chroot.sh ${BUILDROOT} rpm -Uvh --nodeps ${PARENT}/RPMS/x86_64/${RPMPKGFILE}" "$LOG_PATH/filesystem.completed" |
|
96 |
-run_command " Creating symlinks: /tools/bin/{bash,cat,echo,pwd,stty}" "ln -fsv /tools/bin/{bash,cat,echo,pwd,stty} ${BUILDROOT}/bin" "$LOG_PATH/filesystem.completed" |
|
97 |
-run_command " Creating symlinks: /tools/bin/perl /usr/bin" "ln -fsv /tools/bin/perl ${BUILDROOT}/usr/bin" "$LOG_PATH/filesystem.completed" |
|
98 |
-run_command " Creating symlinks: /tools/lib/libgcc_s.so{,.1}" "ln -fsv /tools/lib/libgcc_s.so{,.1} ${BUILDROOT}/usr/lib" "$LOG_PATH/filesystem.completed" |
|
99 |
-run_command " Creating symlinks: /tools/lib/libstdc++.so{,.6} /usr/lib" "ln -fsv /tools/lib/libstdc++.so{,.6} ${BUILDROOT}/usr/lib" "$LOG_PATH/filesystem.completed" |
|
100 |
-[ -z $TOOLS_ARCHIVE ] && \ |
|
101 |
- run_command " Sed: /usr/lib/libstdc++.la" "sed 's/tools/usr/' ${BUILDROOT}/tools/lib/libstdc++.la > ${BUILDROOT}/usr/lib/libstdc++.la" "$LOG_PATH/filesystem.completed" |
|
102 |
-run_command " Creating symlinks: bash /bin/sh" "ln -fsv bash ${BUILDROOT}/bin/sh" "$LOG_PATH/filesystem.completed" |
|
89 |
+run_command " Installing filesystem " "rpm -Uvh --nodeps --root ${BUILDROOT} ${RPM_PATH}/x86_64/${RPMPKGFILE}" "$LOG_PATH/filesystem.completed" |
|
90 |
+ |
|
103 | 91 |
|
104 | 92 |
# Ommited in the filesystem.spec file - not needed for booting |
105 | 93 |
[ -e ${BUILDROOT}/dev/console ] || mknod -m 600 ${BUILDROOT}/dev/console c 5 1 |