base.bbclass: fix a syntax error in one of distclean's exception handlers
[vuplus_openembedded] / classes / base.bbclass
1 BB_DEFAULT_TASK ?= "build"
2
3 # like os.path.join but doesn't treat absolute RHS specially
4 def base_path_join(a, *p):
5     path = a
6     for b in p:
7         if path == '' or path.endswith('/'):
8             path +=  b
9         else:
10             path += '/' + b
11     return path
12
13 # for MD5/SHA handling
14 def base_chk_load_parser(config_path):
15     import ConfigParser, os, bb
16     parser = ConfigParser.ConfigParser()
17     if not len(parser.read(config_path)) == 1:
18         bb.note("Can not open the '%s' ini file" % config_path)
19         raise Exception("Can not open the '%s'" % config_path)
20
21     return parser
22
23 def base_chk_file(parser, pn, pv, src_uri, localpath, data):
24     import os, bb
25     no_checksum = False
26     # Try PN-PV-SRC_URI first and then try PN-SRC_URI
27     # we rely on the get method to create errors
28     pn_pv_src = "%s-%s-%s" % (pn,pv,src_uri)
29     pn_src    = "%s-%s" % (pn,src_uri)
30     if parser.has_section(pn_pv_src):
31         md5    = parser.get(pn_pv_src, "md5")
32         sha256 = parser.get(pn_pv_src, "sha256")
33     elif parser.has_section(pn_src):
34         md5    = parser.get(pn_src, "md5")
35         sha256 = parser.get(pn_src, "sha256")
36     elif parser.has_section(src_uri):
37         md5    = parser.get(src_uri, "md5")
38         sha256 = parser.get(src_uri, "sha256")
39     else:
40         no_checksum = True
41
42     # md5 and sha256 should be valid now
43     if not os.path.exists(localpath):
44         bb.note("The localpath does not exist '%s'" % localpath)
45         raise Exception("The path does not exist '%s'" % localpath)
46
47
48     # call md5(sum) and shasum
49     try:
50         md5pipe = os.popen('md5sum ' + localpath)
51         md5data = (md5pipe.readline().split() or [ "" ])[0]
52         md5pipe.close()
53     except OSError:
54         raise Exception("Executing md5sum failed")
55
56     try:
57         shapipe = os.popen('PATH=%s oe_sha256sum %s' % (bb.data.getVar('PATH', data, True), localpath))
58         shadata = (shapipe.readline().split() or [ "" ])[0]
59         shapipe.close()
60     except OSError:
61         raise Exception("Executing shasum failed")
62
63     if no_checksum == True:     # we do not have conf/checksums.ini entry
64         try:
65             file = open("%s/checksums.ini" % bb.data.getVar("TMPDIR", data, 1), "a")
66         except:
67             return False
68
69         if not file:
70             raise Exception("Creating checksums.ini failed")
71         
72         file.write("[%s]\nmd5=%s\nsha256=%s\n\n" % (src_uri, md5data, shadata))
73         file.close()
74         return False
75
76     if not md5 == md5data:
77         bb.note("The MD5Sums did not match. Wanted: '%s' and Got: '%s'" % (md5,md5data))
78         raise Exception("MD5 Sums do not match. Wanted: '%s' Got: '%s'" % (md5, md5data))
79
80     if not sha256 == shadata:
81         bb.note("The SHA256 Sums do not match. Wanted: '%s' Got: '%s'" % (sha256,shadata))
82         raise Exception("SHA256 Sums do not match. Wanted: '%s' Got: '%s'" % (sha256, shadata))
83
84     return True
85
86
87 def base_dep_prepend(d):
88         import bb
89         #
90         # Ideally this will check a flag so we will operate properly in
91         # the case where host == build == target, for now we don't work in
92         # that case though.
93         #
94         deps = "shasum-native "
95         if bb.data.getVar('PN', d, True) == "shasum-native":
96                 deps = ""
97
98         # INHIBIT_DEFAULT_DEPS doesn't apply to the patch command.  Whether or  not
99         # we need that built is the responsibility of the patch function / class, not
100         # the application.
101         if not bb.data.getVar('INHIBIT_DEFAULT_DEPS', d):
102                 if (bb.data.getVar('HOST_SYS', d, 1) !=
103                     bb.data.getVar('BUILD_SYS', d, 1)):
104                         deps += " virtual/${TARGET_PREFIX}gcc virtual/libc "
105         return deps
106
107 def base_read_file(filename):
108         import bb
109         try:
110                 f = file( filename, "r" )
111         except IOError, reason:
112                 return "" # WARNING: can't raise an error now because of the new RDEPENDS handling. This is a bit ugly. :M:
113         else:
114                 return f.read().strip()
115         return None
116
117 def base_conditional(variable, checkvalue, truevalue, falsevalue, d):
118         import bb
119         if bb.data.getVar(variable,d,1) == checkvalue:
120                 return truevalue
121         else:
122                 return falsevalue
123
124 def base_less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
125         import bb
126         if float(bb.data.getVar(variable,d,1)) <= float(checkvalue):
127                 return truevalue
128         else:
129                 return falsevalue
130
131 def base_version_less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
132     import bb
133     result = bb.vercmp(bb.data.getVar(variable,d,True), checkvalue)
134     if result <= 0:
135         return truevalue
136     else:
137         return falsevalue
138
139 def base_contains(variable, checkvalues, truevalue, falsevalue, d):
140         import bb
141         matches = 0
142         if type(checkvalues).__name__ == "str":
143                 checkvalues = [checkvalues]
144         for value in checkvalues:
145                 if bb.data.getVar(variable,d,1).find(value) != -1:      
146                         matches = matches + 1
147         if matches == len(checkvalues):
148                 return truevalue                
149         return falsevalue
150
151 def base_both_contain(variable1, variable2, checkvalue, d):
152        import bb
153        if bb.data.getVar(variable1,d,1).find(checkvalue) != -1 and bb.data.getVar(variable2,d,1).find(checkvalue) != -1:
154                return checkvalue
155        else:
156                return ""
157
158 DEPENDS_prepend="${@base_dep_prepend(d)} "
159
160 # Returns PN with various suffixes removed
161 # or PN if no matching suffix was found.
162 def base_package_name(d):
163   import bb;
164
165   pn = bb.data.getVar('PN', d, 1)
166   if pn.endswith("-native"):
167                 pn = pn[0:-7]
168   elif pn.endswith("-cross"):
169                 pn = pn[0:-6]
170   elif pn.endswith("-initial"):
171                 pn = pn[0:-8]
172   elif pn.endswith("-intermediate"):
173                 pn = pn[0:-13]
174
175   return pn
176
177 def base_set_filespath(path, d):
178         import os, bb
179         filespath = []
180         # The ":" ensures we have an 'empty' override
181         overrides = (bb.data.getVar("OVERRIDES", d, 1) or "") + ":"
182         for p in path:
183                 for o in overrides.split(":"):
184                         filespath.append(os.path.join(p, o))
185         return ":".join(filespath)
186
187 FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", "${FILE_DIRNAME}/${P}", "${FILE_DIRNAME}/${PN}", "${FILE_DIRNAME}/${BP}", "${FILE_DIRNAME}/${BPN}", "${FILE_DIRNAME}/files", "${FILE_DIRNAME}" ], d)}"
188
189 def oe_filter(f, str, d):
190         from re import match
191         return " ".join(filter(lambda x: match(f, x, 0), str.split()))
192
193 def oe_filter_out(f, str, d):
194         from re import match
195         return " ".join(filter(lambda x: not match(f, x, 0), str.split()))
196
197 die() {
198         oefatal "$*"
199 }
200
201 oenote() {
202         echo "NOTE:" "$*"
203 }
204
205 oewarn() {
206         echo "WARNING:" "$*"
207 }
208
209 oefatal() {
210         echo "FATAL:" "$*"
211         exit 1
212 }
213
214 oedebug() {
215         test $# -ge 2 || {
216                 echo "Usage: oedebug level \"message\""
217                 exit 1
218         }
219
220         test ${OEDEBUG:-0} -ge $1 && {
221                 shift
222                 echo "DEBUG:" $*
223         }
224 }
225
226 oe_runmake() {
227         if [ x"$MAKE" = x ]; then MAKE=make; fi
228         oenote ${MAKE} ${EXTRA_OEMAKE} "$@"
229         ${MAKE} ${EXTRA_OEMAKE} "$@" || die "oe_runmake failed"
230 }
231
232 oe_soinstall() {
233         # Purpose: Install shared library file and
234         #          create the necessary links
235         # Example:
236         #
237         # oe_
238         #
239         #oenote installing shared library $1 to $2
240         #
241         libname=`basename $1`
242         install -m 755 $1 $2/$libname
243         sonamelink=`${HOST_PREFIX}readelf -d $1 |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
244         solink=`echo $libname | sed -e 's/\.so\..*/.so/'`
245         ln -sf $libname $2/$sonamelink
246         ln -sf $libname $2/$solink
247 }
248
249 oe_libinstall() {
250         # Purpose: Install a library, in all its forms
251         # Example
252         #
253         # oe_libinstall libltdl ${STAGING_LIBDIR}/
254         # oe_libinstall -C src/libblah libblah ${D}/${libdir}/
255         dir=""
256         libtool=""
257         silent=""
258         require_static=""
259         require_shared=""
260         staging_install=""
261         while [ "$#" -gt 0 ]; do
262                 case "$1" in
263                 -C)
264                         shift
265                         dir="$1"
266                         ;;
267                 -s)
268                         silent=1
269                         ;;
270                 -a)
271                         require_static=1
272                         ;;
273                 -so)
274                         require_shared=1
275                         ;;
276                 -*)
277                         oefatal "oe_libinstall: unknown option: $1"
278                         ;;
279                 *)
280                         break;
281                         ;;
282                 esac
283                 shift
284         done
285
286         libname="$1"
287         shift
288         destpath="$1"
289         if [ -z "$destpath" ]; then
290                 oefatal "oe_libinstall: no destination path specified"
291         fi
292         if echo "$destpath/" | egrep '^${STAGING_LIBDIR}/' >/dev/null
293         then
294                 staging_install=1
295         fi
296
297         __runcmd () {
298                 if [ -z "$silent" ]; then
299                         echo >&2 "oe_libinstall: $*"
300                 fi
301                 $*
302         }
303
304         if [ -z "$dir" ]; then
305                 dir=`pwd`
306         fi
307
308         dotlai=$libname.lai
309
310         # Sanity check that the libname.lai is unique
311         number_of_files=`(cd $dir; find . -name "$dotlai") | wc -l`
312         if [ $number_of_files -gt 1 ]; then
313                 oefatal "oe_libinstall: $dotlai is not unique in $dir"
314         fi
315
316
317         dir=$dir`(cd $dir;find . -name "$dotlai") | sed "s/^\.//;s/\/$dotlai\$//;q"`
318         olddir=`pwd`
319         __runcmd cd $dir
320
321         lafile=$libname.la
322
323         # If such file doesn't exist, try to cut version suffix
324         if [ ! -f "$lafile" ]; then
325                 libname1=`echo "$libname" | sed 's/-[0-9.]*$//'`
326                 lafile1=$libname.la
327                 if [ -f "$lafile1" ]; then
328                         libname=$libname1
329                         lafile=$lafile1
330                 fi
331         fi
332
333         if [ -f "$lafile" ]; then
334                 # libtool archive
335                 eval `cat $lafile|grep "^library_names="`
336                 libtool=1
337         else
338                 library_names="$libname.so* $libname.dll.a"
339         fi
340
341         __runcmd install -d $destpath/
342         dota=$libname.a
343         if [ -f "$dota" -o -n "$require_static" ]; then
344                 __runcmd install -m 0644 $dota $destpath/
345         fi
346         if [ -f "$dotlai" -a -n "$libtool" ]; then
347                 if test -n "$staging_install"
348                 then
349                         # stop libtool using the final directory name for libraries
350                         # in staging:
351                         __runcmd rm -f $destpath/$libname.la
352                         __runcmd sed -e 's/^installed=yes$/installed=no/' \
353                                      -e '/^dependency_libs=/s,${WORKDIR}[[:alnum:]/\._+-]*/\([[:alnum:]\._+-]*\),${STAGING_LIBDIR}/\1,g' \
354                                      -e "/^dependency_libs=/s,\([[:space:]']\)${libdir},\1${STAGING_LIBDIR},g" \
355                                      $dotlai >$destpath/$libname.la
356                 else
357                         __runcmd install -m 0644 $dotlai $destpath/$libname.la
358                 fi
359         fi
360
361         for name in $library_names; do
362                 files=`eval echo $name`
363                 for f in $files; do
364                         if [ ! -e "$f" ]; then
365                                 if [ -n "$libtool" ]; then
366                                         oefatal "oe_libinstall: $dir/$f not found."
367                                 fi
368                         elif [ -L "$f" ]; then
369                                 __runcmd cp -P "$f" $destpath/
370                         elif [ ! -L "$f" ]; then
371                                 libfile="$f"
372                                 __runcmd install -m 0755 $libfile $destpath/
373                         fi
374                 done
375         done
376
377         if [ -z "$libfile" ]; then
378                 if  [ -n "$require_shared" ]; then
379                         oefatal "oe_libinstall: unable to locate shared library"
380                 fi
381         elif [ -z "$libtool" ]; then
382                 # special case hack for non-libtool .so.#.#.# links
383                 baselibfile=`basename "$libfile"`
384                 if (echo $baselibfile | grep -qE '^lib.*\.so\.[0-9.]*$'); then
385                         sonamelink=`${HOST_PREFIX}readelf -d $libfile |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
386                         solink=`echo $baselibfile | sed -e 's/\.so\..*/.so/'`
387                         if [ -n "$sonamelink" -a x"$baselibfile" != x"$sonamelink" ]; then
388                                 __runcmd ln -sf $baselibfile $destpath/$sonamelink
389                         fi
390                         __runcmd ln -sf $baselibfile $destpath/$solink
391                 fi
392         fi
393
394         __runcmd cd "$olddir"
395 }
396
397 def package_stagefile(file, d):
398     import bb, os
399
400     if bb.data.getVar('PSTAGING_ACTIVE', d, True) == "1":
401         destfile = file.replace(bb.data.getVar("TMPDIR", d, 1), bb.data.getVar("PSTAGE_TMPDIR_STAGE", d, 1))
402         bb.mkdirhier(os.path.dirname(destfile))
403         #print "%s to %s" % (file, destfile)
404         bb.copyfile(file, destfile)
405
406 package_stagefile_shell() {
407         if [ "$PSTAGING_ACTIVE" = "1" ]; then
408                 srcfile=$1
409                 destfile=`echo $srcfile | sed s#${TMPDIR}#${PSTAGE_TMPDIR_STAGE}#`
410                 destdir=`dirname $destfile`
411                 mkdir -p $destdir
412                 cp -dp $srcfile $destfile
413         fi
414 }
415
416 oe_machinstall() {
417         # Purpose: Install machine dependent files, if available
418         #          If not available, check if there is a default
419         #          If no default, just touch the destination
420         # Example:
421         #                $1  $2   $3         $4
422         # oe_machinstall -m 0644 fstab ${D}/etc/fstab
423         #
424         # TODO: Check argument number?
425         #
426         filename=`basename $3`
427         dirname=`dirname $3`
428
429         for o in `echo ${OVERRIDES} | tr ':' ' '`; do
430                 if [ -e $dirname/$o/$filename ]; then
431                         oenote $dirname/$o/$filename present, installing to $4
432                         install $1 $2 $dirname/$o/$filename $4
433                         return
434                 fi
435         done
436 #       oenote overrides specific file NOT present, trying default=$3...
437         if [ -e $3 ]; then
438                 oenote $3 present, installing to $4
439                 install $1 $2 $3 $4
440         else
441                 oenote $3 NOT present, touching empty $4
442                 touch $4
443         fi
444 }
445
446 addtask listtasks
447 do_listtasks[nostamp] = "1"
448 python do_listtasks() {
449         import sys
450         # emit variables and shell functions
451         #bb.data.emit_env(sys.__stdout__, d)
452         # emit the metadata which isnt valid shell
453         for e in d.keys():
454                 if bb.data.getVarFlag(e, 'task', d):
455                         sys.__stdout__.write("%s\n" % e)
456 }
457
458 addtask clean
459 do_clean[dirs] = "${TOPDIR}"
460 do_clean[nostamp] = "1"
461 python base_do_clean() {
462         """clear the build and temp directories"""
463         dir = bb.data.expand("${WORKDIR}", d)
464         if dir == '//': raise bb.build.FuncFailed("wrong DATADIR")
465         bb.note("removing " + dir)
466         os.system('rm -rf ' + dir)
467
468         dir = "%s.*" % bb.data.expand(bb.data.getVar('STAMP', d), d)
469         bb.note("removing " + dir)
470         os.system('rm -f '+ dir)
471 }
472
473 #Uncomment this for bitbake 1.8.12
474 #addtask rebuild after do_${BB_DEFAULT_TASK}
475 addtask rebuild
476 do_rebuild[dirs] = "${TOPDIR}"
477 do_rebuild[nostamp] = "1"
478 python base_do_rebuild() {
479         """rebuild a package"""
480         from bb import __version__
481         try:
482                 from distutils.version import LooseVersion
483         except ImportError:
484                 def LooseVersion(v): print "WARNING: sanity.bbclass can't compare versions without python-distutils"; return 1
485         if (LooseVersion(__version__) < LooseVersion('1.8.11')):
486                 bb.build.exec_func('do_clean', d)
487                 bb.build.exec_task('do_' + bb.data.getVar('BB_DEFAULT_TASK', d, 1), d)
488 }
489
490 addtask mrproper
491 do_mrproper[dirs] = "${TOPDIR}"
492 do_mrproper[nostamp] = "1"
493 python base_do_mrproper() {
494         """clear downloaded sources, build and temp directories"""
495         dir = bb.data.expand("${DL_DIR}", d)
496         if dir == '/': bb.build.FuncFailed("wrong DATADIR")
497         bb.debug(2, "removing " + dir)
498         os.system('rm -rf ' + dir)
499         bb.build.exec_func('do_clean', d)
500 }
501
502 addtask distclean
503 do_distclean[dirs] = "${TOPDIR}"
504 do_distclean[nostamp] = "1"
505 python base_do_distclean() {
506         """clear downloaded sources, build and temp directories"""
507         import os
508
509         bb.build.exec_func('do_clean', d)
510
511         src_uri = bb.data.getVar('SRC_URI', d, 1)
512         if not src_uri:
513                 return
514
515         for uri in src_uri.split():
516                 if bb.decodeurl(uri)[0] == "file":
517                         continue
518
519                 try:
520                         local = bb.data.expand(bb.fetch.localpath(uri, d), d)
521                 except bb.MalformedUrl, e:
522                         bb.debug(1, 'Unable to generate local path for malformed uri: %s' % e)
523                 else:
524                         bb.note("removing %s" % local)
525                         try:
526                                 if os.path.exists(local + ".md5"):
527                                         os.remove(local + ".md5")
528                                 if os.path.exists(local):
529                                         os.remove(local)
530                         except OSError, e:
531                                 bb.note("Error in removal: %s" % e)
532 }
533
534 SCENEFUNCS += "base_scenefunction"
535                                                                                         
536 python base_do_setscene () {
537         for f in (bb.data.getVar('SCENEFUNCS', d, 1) or '').split():
538                 bb.build.exec_func(f, d)
539         if not os.path.exists(bb.data.getVar('STAMP', d, 1) + ".do_setscene"):
540                 bb.build.make_stamp("do_setscene", d)
541 }
542 do_setscene[selfstamp] = "1"
543 addtask setscene before do_fetch
544
545 python base_scenefunction () {
546         stamp = bb.data.getVar('STAMP', d, 1) + ".needclean"
547         if os.path.exists(stamp):
548                 bb.build.exec_func("do_clean", d)
549 }
550
551
552 addtask fetch
553 do_fetch[dirs] = "${DL_DIR}"
554 do_fetch[depends] = "shasum-native:do_populate_staging"
555 python base_do_fetch() {
556         import sys
557
558         localdata = bb.data.createCopy(d)
559         bb.data.update_data(localdata)
560
561         src_uri = bb.data.getVar('SRC_URI', localdata, 1)
562         if not src_uri:
563                 return 1
564
565         try:
566                 bb.fetch.init(src_uri.split(),d)
567         except bb.fetch.NoMethodError:
568                 (type, value, traceback) = sys.exc_info()
569                 raise bb.build.FuncFailed("No method: %s" % value)
570
571         try:
572                 bb.fetch.go(localdata)
573         except bb.fetch.MissingParameterError:
574                 (type, value, traceback) = sys.exc_info()
575                 raise bb.build.FuncFailed("Missing parameters: %s" % value)
576         except bb.fetch.FetchError:
577                 (type, value, traceback) = sys.exc_info()
578                 raise bb.build.FuncFailed("Fetch failed: %s" % value)
579         except bb.fetch.MD5SumError:
580                 (type, value, traceback) = sys.exc_info()
581                 raise bb.build.FuncFailed("MD5  failed: %s" % value)
582         except:
583                 (type, value, traceback) = sys.exc_info()
584                 raise bb.build.FuncFailed("Unknown fetch Error: %s" % value)
585
586
587         # Verify the SHA and MD5 sums we have in OE and check what do
588         # in
589         check_sum = bb.which(bb.data.getVar('BBPATH', d, True), "conf/checksums.ini")
590         if not check_sum:
591                 bb.note("No conf/checksums.ini found, not checking checksums")
592                 return
593
594         try:
595                 parser = base_chk_load_parser(check_sum)
596         except:
597                 bb.note("Creating the CheckSum parser failed")
598                 return
599
600         pv = bb.data.getVar('PV', d, True)
601         pn = bb.data.getVar('PN', d, True)
602
603         # Check each URI
604         for url in src_uri.split():
605                 localpath = bb.data.expand(bb.fetch.localpath(url, localdata), localdata)
606                 (type,host,path,_,_,_) = bb.decodeurl(url)
607                 uri = "%s://%s%s" % (type,host,path)
608                 try:
609                         if type == "http" or type == "https" or type == "ftp" or type == "ftps":
610                                 if not base_chk_file(parser, pn, pv,uri, localpath, d):
611                                         if not bb.data.getVar("OE_ALLOW_INSECURE_DOWNLOADS",d, True):
612                                                 bb.fatal("%s-%s: %s has no entry in conf/checksums.ini, not checking URI" % (pn,pv,uri))
613                                         else:
614                                                 bb.note("%s-%s: %s has no entry in conf/checksums.ini, not checking URI" % (pn,pv,uri))
615                 except Exception:
616                         raise bb.build.FuncFailed("Checksum of '%s' failed" % uri)
617 }
618
619 addtask fetchall after do_fetch
620 do_fetchall[recrdeptask] = "do_fetch"
621 base_do_fetchall() {
622         :
623 }
624
625 addtask checkuri
626 do_checkuri[nostamp] = "1"
627 python do_checkuri() {
628         import sys
629
630         localdata = bb.data.createCopy(d)
631         bb.data.update_data(localdata)
632
633         src_uri = bb.data.getVar('SRC_URI', localdata, 1)
634
635         try:
636                 bb.fetch.init(src_uri.split(),d)
637         except bb.fetch.NoMethodError:
638                 (type, value, traceback) = sys.exc_info()
639                 raise bb.build.FuncFailed("No method: %s" % value)
640
641         try:
642                 bb.fetch.checkstatus(localdata)
643         except bb.fetch.MissingParameterError:
644                 (type, value, traceback) = sys.exc_info()
645                 raise bb.build.FuncFailed("Missing parameters: %s" % value)
646         except bb.fetch.FetchError:
647                 (type, value, traceback) = sys.exc_info()
648                 raise bb.build.FuncFailed("Fetch failed: %s" % value)
649         except bb.fetch.MD5SumError:
650                 (type, value, traceback) = sys.exc_info()
651                 raise bb.build.FuncFailed("MD5  failed: %s" % value)
652         except:
653                 (type, value, traceback) = sys.exc_info()
654                 raise bb.build.FuncFailed("Unknown fetch Error: %s" % value)
655 }
656
657 addtask checkuriall after do_checkuri
658 do_checkuriall[recrdeptask] = "do_checkuri"
659 do_checkuriall[nostamp] = "1"
660 base_do_checkuriall() {
661         :
662 }
663
664 addtask buildall after do_build
665 do_buildall[recrdeptask] = "do_build"
666 base_do_buildall() {
667         :
668 }
669
670
671 def oe_unpack_file(file, data, url = None):
672         import bb, os
673         if not url:
674                 url = "file://%s" % file
675         dots = file.split(".")
676         if dots[-1] in ['gz', 'bz2', 'Z']:
677                 efile = os.path.join(bb.data.getVar('WORKDIR', data, 1),os.path.basename('.'.join(dots[0:-1])))
678         else:
679                 efile = file
680         cmd = None
681         if file.endswith('.tar'):
682                 cmd = 'tar x --no-same-owner -f %s' % file
683         elif file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
684                 cmd = 'tar xz --no-same-owner -f %s' % file
685         elif file.endswith('.tbz') or file.endswith('.tbz2') or file.endswith('.tar.bz2'):
686                 cmd = 'bzip2 -dc %s | tar x --no-same-owner -f -' % file
687         elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'):
688                 cmd = 'gzip -dc %s > %s' % (file, efile)
689         elif file.endswith('.bz2'):
690                 cmd = 'bzip2 -dc %s > %s' % (file, efile)
691         elif file.endswith('.zip') or file.endswith('.jar'):
692                 cmd = 'unzip -q -o'
693                 (type, host, path, user, pswd, parm) = bb.decodeurl(url)
694                 if 'dos' in parm:
695                         cmd = '%s -a' % cmd
696                 cmd = '%s %s' % (cmd, file)
697         elif os.path.isdir(file):
698                 filesdir = os.path.realpath(bb.data.getVar("FILESDIR", data, 1))
699                 destdir = "."
700                 if file[0:len(filesdir)] == filesdir:
701                         destdir = file[len(filesdir):file.rfind('/')]
702                         destdir = destdir.strip('/')
703                         if len(destdir) < 1:
704                                 destdir = "."
705                         elif not os.access("%s/%s" % (os.getcwd(), destdir), os.F_OK):
706                                 os.makedirs("%s/%s" % (os.getcwd(), destdir))
707                 cmd = 'cp -pPR %s %s/%s/' % (file, os.getcwd(), destdir)
708         else:
709                 (type, host, path, user, pswd, parm) = bb.decodeurl(url)
710                 if not 'patch' in parm:
711                         # The "destdir" handling was specifically done for FILESPATH
712                         # items.  So, only do so for file:// entries.
713                         if type == "file":
714                                 destdir = bb.decodeurl(url)[1] or "."
715                         else:
716                                 destdir = "."
717                         bb.mkdirhier("%s/%s" % (os.getcwd(), destdir))
718                         cmd = 'cp %s %s/%s/' % (file, os.getcwd(), destdir)
719
720         if not cmd:
721                 return True
722
723         dest = os.path.join(os.getcwd(), os.path.basename(file))
724         if os.path.exists(dest):
725                 if os.path.samefile(file, dest):
726                         return True
727
728         cmd = "PATH=\"%s\" %s" % (bb.data.getVar('PATH', data, 1), cmd)
729         bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
730         ret = os.system(cmd)
731         return ret == 0
732
733 addtask unpack after do_fetch
734 do_unpack[dirs] = "${WORKDIR}"
735 python base_do_unpack() {
736         import re, os
737
738         localdata = bb.data.createCopy(d)
739         bb.data.update_data(localdata)
740
741         src_uri = bb.data.getVar('SRC_URI', localdata)
742         if not src_uri:
743                 return
744         src_uri = bb.data.expand(src_uri, localdata)
745         for url in src_uri.split():
746                 try:
747                         local = bb.data.expand(bb.fetch.localpath(url, localdata), localdata)
748                 except bb.MalformedUrl, e:
749                         raise FuncFailed('Unable to generate local path for malformed uri: %s' % e)
750                 local = os.path.realpath(local)
751                 ret = oe_unpack_file(local, localdata, url)
752                 if not ret:
753                         raise bb.build.FuncFailed()
754 }
755
756 def base_get_scmbasepath(d):
757         import bb
758         path_to_bbfiles = bb.data.getVar( 'BBFILES', d, 1 ).split()
759         return path_to_bbfiles[0][:path_to_bbfiles[0].rindex( "packages" )]
760
761 def base_get_metadata_monotone_branch(d):
762         monotone_branch = "<unknown>"
763         try:
764                 monotone_branch = file( "%s/_MTN/options" % base_get_scmbasepath(d) ).read().strip()
765                 if monotone_branch.startswith( "database" ):
766                         monotone_branch_words = monotone_branch.split()
767                         monotone_branch = monotone_branch_words[ monotone_branch_words.index( "branch" )+1][1:-1]
768         except:
769                 pass
770         return monotone_branch
771
772 def base_get_metadata_monotone_revision(d):
773         monotone_revision = "<unknown>"
774         try:
775                 monotone_revision = file( "%s/_MTN/revision" % base_get_scmbasepath(d) ).read().strip()
776                 if monotone_revision.startswith( "format_version" ):
777                         monotone_revision_words = monotone_revision.split()
778                         monotone_revision = monotone_revision_words[ monotone_revision_words.index( "old_revision" )+1][1:-1]
779         except IOError:
780                 pass
781         return monotone_revision
782
783 def base_get_metadata_svn_revision(d):
784         revision = "<unknown>"
785         try:
786                 revision = file( "%s/.svn/entries" % base_get_scmbasepath(d) ).readlines()[3].strip()
787         except IOError:
788                 pass
789         return revision
790
791 def base_get_metadata_git_branch(d):
792         import os
793         branch = os.popen('cd %s; git branch | grep "^* " | tr -d "* "' % base_get_scmbasepath(d)).read()
794
795         if len(branch) != 0:
796                 return branch
797         return "<unknown>"
798
799 def base_get_metadata_git_revision(d):
800         import os
801         rev = os.popen("cd %s; git log -n 1 --pretty=oneline --" % base_get_scmbasepath(d)).read().split(" ")[0]
802         if len(rev) != 0:
803                 return rev
804         return "<unknown>"
805
806 def base_detect_revision(d):
807         scms = [base_get_metadata_monotone_revision, \
808                         base_get_metadata_svn_revision, \
809                         base_get_metadata_git_revision]
810
811         for scm in scms:
812                 rev = scm(d)
813                 if rev <> "<unknown>":
814                         return rev
815
816         return "<unknown>"      
817
818 def base_detect_branch(d):
819         scms = [base_get_metadata_monotone_branch, \
820                         base_get_metadata_git_branch]
821
822         for scm in scms:
823                 rev = scm(d)
824                 if rev <> "<unknown>":
825                         return rev.strip()
826
827         return "<unknown>"      
828         
829         
830
831 METADATA_BRANCH ?= "${@base_detect_branch(d)}"
832 METADATA_REVISION ?= "${@base_detect_revision(d)}"
833
834 addhandler base_eventhandler
835 python base_eventhandler() {
836         from bb import note, error, data
837         from bb.event import Handled, NotHandled, getName
838         import os
839
840         messages = {}
841         messages["Completed"] = "completed"
842         messages["Succeeded"] = "completed"
843         messages["Started"] = "started"
844         messages["Failed"] = "failed"
845
846         name = getName(e)
847         msg = ""
848         if name.startswith("Pkg"):
849                 msg += "package %s: " % data.getVar("P", e.data, 1)
850                 msg += messages.get(name[3:]) or name[3:]
851         elif name.startswith("Task"):
852                 msg += "package %s: task %s: " % (data.getVar("PF", e.data, 1), e.task)
853                 msg += messages.get(name[4:]) or name[4:]
854         elif name.startswith("Build"):
855                 msg += "build %s: " % e.name
856                 msg += messages.get(name[5:]) or name[5:]
857         elif name == "UnsatisfiedDep":
858                 msg += "package %s: dependency %s %s" % (e.pkg, e.dep, name[:-3].lower())
859         if msg:
860                 note(msg)
861
862         if name.startswith("BuildStarted"):
863                 bb.data.setVar( 'BB_VERSION', bb.__version__, e.data )
864                 statusvars = ['BB_VERSION', 'METADATA_BRANCH', 'METADATA_REVISION', 'TARGET_ARCH', 'TARGET_OS', 'MACHINE', 'DISTRO', 'DISTRO_VERSION','TARGET_FPU']
865                 statuslines = ["%-17s = \"%s\"" % (i, bb.data.getVar(i, e.data, 1) or '') for i in statusvars]
866                 statusmsg = "\nOE Build Configuration:\n%s\n" % '\n'.join(statuslines)
867                 print statusmsg
868
869                 needed_vars = [ "TARGET_ARCH", "TARGET_OS" ]
870                 pesteruser = []
871                 for v in needed_vars:
872                         val = bb.data.getVar(v, e.data, 1)
873                         if not val or val == 'INVALID':
874                                 pesteruser.append(v)
875                 if pesteruser:
876                         bb.fatal('The following variable(s) were not set: %s\nPlease set them directly, or choose a MACHINE or DISTRO that sets them.' % ', '.join(pesteruser))
877
878         #
879         # Handle removing stamps for 'rebuild' task
880         #
881         if name.startswith("StampUpdate"):
882                 for (fn, task) in e.targets:
883                         #print "%s %s" % (task, fn)         
884                         if task == "do_rebuild":
885                                 dir = "%s.*" % e.stampPrefix[fn]
886                                 bb.note("Removing stamps: " + dir)
887                                 os.system('rm -f '+ dir)
888                                 os.system('touch ' + e.stampPrefix[fn] + '.needclean')
889
890         if not data in e.__dict__:
891                 return NotHandled
892
893         log = data.getVar("EVENTLOG", e.data, 1)
894         if log:
895                 logfile = file(log, "a")
896                 logfile.write("%s\n" % msg)
897                 logfile.close()
898
899         return NotHandled
900 }
901
902 addtask configure after do_unpack do_patch
903 do_configure[dirs] = "${S} ${B}"
904 do_configure[deptask] = "do_populate_staging"
905 base_do_configure() {
906         :
907 }
908
909 addtask compile after do_configure
910 do_compile[dirs] = "${S} ${B}"
911 base_do_compile() {
912         if [ -e Makefile -o -e makefile ]; then
913                 oe_runmake || die "make failed"
914         else
915                 oenote "nothing to compile"
916         fi
917 }
918
919 base_do_stage () {
920         :
921 }
922
923 do_populate_staging[dirs] = "${STAGING_DIR_TARGET}/${layout_bindir} ${STAGING_DIR_TARGET}/${layout_libdir} \
924                              ${STAGING_DIR_TARGET}/${layout_includedir} \
925                              ${STAGING_BINDIR_NATIVE} ${STAGING_LIBDIR_NATIVE} \
926                              ${STAGING_INCDIR_NATIVE} \
927                              ${STAGING_DATADIR} \
928                              ${S} ${B}"
929
930 # Could be compile but populate_staging and do_install shouldn't run at the same time
931 addtask populate_staging after do_install
932
933 python do_populate_staging () {
934     bb.build.exec_func('do_stage', d)
935 }
936
937 addtask install after do_compile
938 do_install[dirs] = "${D} ${S} ${B}"
939 # Remove and re-create ${D} so that is it guaranteed to be empty
940 do_install[cleandirs] = "${D}"
941
942 base_do_install() {
943         :
944 }
945
946 base_do_package() {
947         :
948 }
949
950 addtask build after do_populate_staging
951 do_build = ""
952 do_build[func] = "1"
953
954 # Functions that update metadata based on files outputted
955 # during the build process.
956
957 def explode_deps(s):
958         r = []
959         l = s.split()
960         flag = False
961         for i in l:
962                 if i[0] == '(':
963                         flag = True
964                         j = []
965                 if flag:
966                         j.append(i)
967                         if i.endswith(')'):
968                                 flag = False
969                                 r[-1] += ' ' + ' '.join(j)
970                 else:
971                         r.append(i)
972         return r
973
974 def packaged(pkg, d):
975         import os, bb
976         return os.access(get_subpkgedata_fn(pkg, d) + '.packaged', os.R_OK)
977
978 def read_pkgdatafile(fn):
979         pkgdata = {}
980
981         def decode(str):
982                 import codecs
983                 c = codecs.getdecoder("string_escape")
984                 return c(str)[0]
985
986         import os
987         if os.access(fn, os.R_OK):
988                 import re
989                 f = file(fn, 'r')
990                 lines = f.readlines()
991                 f.close()
992                 r = re.compile("([^:]+):\s*(.*)")
993                 for l in lines:
994                         m = r.match(l)
995                         if m:
996                                 pkgdata[m.group(1)] = decode(m.group(2))
997
998         return pkgdata
999
1000 def get_subpkgedata_fn(pkg, d):
1001         import bb, os
1002         archs = bb.data.expand("${PACKAGE_ARCHS}", d).split(" ")
1003         archs.reverse()
1004         pkgdata = bb.data.expand('${TMPDIR}/pkgdata/', d)
1005         targetdir = bb.data.expand('${TARGET_VENDOR}-${TARGET_OS}/runtime/', d)
1006         for arch in archs:
1007                 fn = pkgdata + arch + targetdir + pkg
1008                 if os.path.exists(fn):
1009                         return fn
1010         return bb.data.expand('${PKGDATA_DIR}/runtime/%s' % pkg, d)
1011
1012 def has_subpkgdata(pkg, d):
1013         import bb, os
1014         return os.access(get_subpkgedata_fn(pkg, d), os.R_OK)
1015
1016 def read_subpkgdata(pkg, d):
1017         import bb
1018         return read_pkgdatafile(get_subpkgedata_fn(pkg, d))
1019
1020 def has_pkgdata(pn, d):
1021         import bb, os
1022         fn = bb.data.expand('${PKGDATA_DIR}/%s' % pn, d)
1023         return os.access(fn, os.R_OK)
1024
1025 def read_pkgdata(pn, d):
1026         import bb
1027         fn = bb.data.expand('${PKGDATA_DIR}/%s' % pn, d)
1028         return read_pkgdatafile(fn)
1029
1030 python read_subpackage_metadata () {
1031         import bb
1032         data = read_pkgdata(bb.data.getVar('PN', d, 1), d)
1033
1034         for key in data.keys():
1035                 bb.data.setVar(key, data[key], d)
1036
1037         for pkg in bb.data.getVar('PACKAGES', d, 1).split():
1038                 sdata = read_subpkgdata(pkg, d)
1039                 for key in sdata.keys():
1040                         bb.data.setVar(key, sdata[key], d)
1041 }
1042
1043 # Make sure MACHINE isn't exported
1044 # (breaks binutils at least)
1045 MACHINE[unexport] = "1"
1046
1047 # Make sure TARGET_ARCH isn't exported
1048 # (breaks Makefiles using implicit rules, e.g. quilt, as GNU make has this 
1049 # in them, undocumented)
1050 TARGET_ARCH[unexport] = "1"
1051
1052 # Make sure DISTRO isn't exported
1053 # (breaks sysvinit at least)
1054 DISTRO[unexport] = "1"
1055
1056
1057 def base_after_parse(d):
1058     import bb, os, exceptions
1059
1060     source_mirror_fetch = bb.data.getVar('SOURCE_MIRROR_FETCH', d, 0)
1061     if not source_mirror_fetch:
1062         need_host = bb.data.getVar('COMPATIBLE_HOST', d, 1)
1063         if need_host:
1064             import re
1065             this_host = bb.data.getVar('HOST_SYS', d, 1)
1066             if not re.match(need_host, this_host):
1067                 raise bb.parse.SkipPackage("incompatible with host %s" % this_host)
1068
1069         need_machine = bb.data.getVar('COMPATIBLE_MACHINE', d, 1)
1070         if need_machine:
1071             import re
1072             this_machine = bb.data.getVar('MACHINE', d, 1)
1073             if this_machine and not re.match(need_machine, this_machine):
1074                 raise bb.parse.SkipPackage("incompatible with machine %s" % this_machine)
1075
1076     pn = bb.data.getVar('PN', d, 1)
1077
1078     # OBSOLETE in bitbake 1.7.4
1079     srcdate = bb.data.getVar('SRCDATE_%s' % pn, d, 1)
1080     if srcdate != None:
1081         bb.data.setVar('SRCDATE', srcdate, d)
1082
1083     use_nls = bb.data.getVar('USE_NLS_%s' % pn, d, 1)
1084     if use_nls != None:
1085         bb.data.setVar('USE_NLS', use_nls, d)
1086
1087     # Git packages should DEPEND on git-native
1088     srcuri = bb.data.getVar('SRC_URI', d, 1)
1089     if "git://" in srcuri:
1090         depends = bb.data.getVarFlag('do_fetch', 'depends', d) or ""
1091         depends = depends + " git-native:do_populate_staging"
1092         bb.data.setVarFlag('do_fetch', 'depends', depends, d)
1093
1094     # 'multimachine' handling
1095     mach_arch = bb.data.getVar('MACHINE_ARCH', d, 1)
1096     pkg_arch = bb.data.getVar('PACKAGE_ARCH', d, 1)
1097
1098     if (pkg_arch == mach_arch):
1099         # Already machine specific - nothing further to do
1100         return
1101
1102     #
1103     # We always try to scan SRC_URI for urls with machine overrides
1104     # unless the package sets SRC_URI_OVERRIDES_PACKAGE_ARCH=0
1105     #
1106     override = bb.data.getVar('SRC_URI_OVERRIDES_PACKAGE_ARCH', d, 1)
1107     if override != '0':
1108         paths = []
1109         for p in [ "${PF}", "${P}", "${PN}", "files", "" ]:
1110             path = bb.data.expand(os.path.join("${FILE_DIRNAME}", p, "${MACHINE}"), d)
1111             if os.path.isdir(path):
1112                 paths.append(path)
1113         if len(paths) != 0:
1114             for s in srcuri.split():
1115                 if not s.startswith("file://"):
1116                     continue
1117                 local = bb.data.expand(bb.fetch.localpath(s, d), d)
1118                 for mp in paths:
1119                     if local.startswith(mp):
1120                         #bb.note("overriding PACKAGE_ARCH from %s to %s" % (pkg_arch, mach_arch))
1121                         bb.data.setVar('PACKAGE_ARCH', "${MACHINE_ARCH}", d)
1122                         bb.data.setVar('MULTIMACH_ARCH', mach_arch, d)
1123                         return
1124
1125     multiarch = pkg_arch
1126
1127     packages = bb.data.getVar('PACKAGES', d, 1).split()
1128     for pkg in packages:
1129         pkgarch = bb.data.getVar("PACKAGE_ARCH_%s" % pkg, d, 1)
1130
1131         # We could look for != PACKAGE_ARCH here but how to choose 
1132         # if multiple differences are present?
1133         # Look through PACKAGE_ARCHS for the priority order?
1134         if pkgarch and pkgarch == mach_arch:
1135             multiarch = mach_arch
1136             break
1137
1138     bb.data.setVar('MULTIMACH_ARCH', multiarch, d)
1139
1140 python () {
1141     import bb
1142     from bb import __version__
1143     base_after_parse(d)
1144
1145     # Remove this for bitbake 1.8.12
1146     try:
1147         from distutils.version import LooseVersion
1148     except ImportError:
1149         def LooseVersion(v): print "WARNING: sanity.bbclass can't compare versions without python-distutils"; return 1
1150     if (LooseVersion(__version__) >= LooseVersion('1.8.11')):
1151         deps = bb.data.getVarFlag('do_rebuild', 'deps', d) or []
1152         deps.append('do_' + bb.data.getVar('BB_DEFAULT_TASK', d, 1))
1153         bb.data.setVarFlag('do_rebuild', 'deps', deps, d)
1154 }
1155
1156 def check_app_exists(app, d):
1157         from bb import which, data
1158
1159         app = data.expand(app, d)
1160         path = data.getVar('PATH', d, 1)
1161         return len(which(path, app)) != 0
1162
1163 def check_gcc3(data):
1164
1165         gcc3_versions = 'gcc-3.4 gcc34 gcc-3.4.4 gcc-3.4.6 gcc-3.4.7 gcc-3.3 gcc33 gcc-3.3.6 gcc-3.2 gcc32'
1166
1167         for gcc3 in gcc3_versions.split():
1168                 if check_app_exists(gcc3, data):
1169                         return gcc3
1170         
1171         return False
1172
1173 # Patch handling
1174 inherit patch
1175
1176 # Configuration data from site files
1177 # Move to autotools.bbclass?
1178 inherit siteinfo
1179
1180 EXPORT_FUNCTIONS do_setscene do_clean do_mrproper do_distclean do_fetch do_unpack do_configure do_compile do_install do_package do_populate_pkgs do_stage do_rebuild do_fetchall
1181
1182 MIRRORS[func] = "0"
1183 MIRRORS () {
1184 ${DEBIAN_MIRROR}/main   http://snapshot.debian.net/archive/pool
1185 ${DEBIAN_MIRROR}        ftp://ftp.de.debian.org/debian/pool
1186 ${DEBIAN_MIRROR}        ftp://ftp.au.debian.org/debian/pool
1187 ${DEBIAN_MIRROR}        ftp://ftp.cl.debian.org/debian/pool
1188 ${DEBIAN_MIRROR}        ftp://ftp.hr.debian.org/debian/pool
1189 ${DEBIAN_MIRROR}        ftp://ftp.fi.debian.org/debian/pool
1190 ${DEBIAN_MIRROR}        ftp://ftp.hk.debian.org/debian/pool
1191 ${DEBIAN_MIRROR}        ftp://ftp.hu.debian.org/debian/pool
1192 ${DEBIAN_MIRROR}        ftp://ftp.ie.debian.org/debian/pool
1193 ${DEBIAN_MIRROR}        ftp://ftp.it.debian.org/debian/pool
1194 ${DEBIAN_MIRROR}        ftp://ftp.jp.debian.org/debian/pool
1195 ${DEBIAN_MIRROR}        ftp://ftp.no.debian.org/debian/pool
1196 ${DEBIAN_MIRROR}        ftp://ftp.pl.debian.org/debian/pool
1197 ${DEBIAN_MIRROR}        ftp://ftp.ro.debian.org/debian/pool
1198 ${DEBIAN_MIRROR}        ftp://ftp.si.debian.org/debian/pool
1199 ${DEBIAN_MIRROR}        ftp://ftp.es.debian.org/debian/pool
1200 ${DEBIAN_MIRROR}        ftp://ftp.se.debian.org/debian/pool
1201 ${DEBIAN_MIRROR}        ftp://ftp.tr.debian.org/debian/pool
1202 ${GNU_MIRROR}   ftp://mirrors.kernel.org/gnu
1203 ${GNU_MIRROR}   ftp://ftp.matrix.com.br/pub/gnu
1204 ${GNU_MIRROR}   ftp://ftp.cs.ubc.ca/mirror2/gnu
1205 ${GNU_MIRROR}   ftp://sunsite.ust.hk/pub/gnu
1206 ${GNU_MIRROR}   ftp://ftp.ayamura.org/pub/gnu
1207 ${KERNELORG_MIRROR}     http://www.kernel.org/pub
1208 ${KERNELORG_MIRROR}     ftp://ftp.us.kernel.org/pub
1209 ${KERNELORG_MIRROR}     ftp://ftp.uk.kernel.org/pub
1210 ${KERNELORG_MIRROR}     ftp://ftp.hk.kernel.org/pub
1211 ${KERNELORG_MIRROR}     ftp://ftp.au.kernel.org/pub
1212 ${KERNELORG_MIRROR}     ftp://ftp.jp.kernel.org/pub
1213 ftp://ftp.gnupg.org/gcrypt/     ftp://ftp.franken.de/pub/crypt/mirror/ftp.gnupg.org/gcrypt/
1214 ftp://ftp.gnupg.org/gcrypt/     ftp://ftp.surfnet.nl/pub/security/gnupg/
1215 ftp://ftp.gnupg.org/gcrypt/     http://gulus.USherbrooke.ca/pub/appl/GnuPG/
1216 ftp://dante.ctan.org/tex-archive ftp://ftp.fu-berlin.de/tex/CTAN
1217 ftp://dante.ctan.org/tex-archive http://sunsite.sut.ac.jp/pub/archives/ctan/
1218 ftp://dante.ctan.org/tex-archive http://ctan.unsw.edu.au/
1219 ftp://ftp.gnutls.org/pub/gnutls ftp://ftp.gnutls.org/pub/gnutls/
1220 ftp://ftp.gnutls.org/pub/gnutls ftp://ftp.gnupg.org/gcrypt/gnutls/
1221 ftp://ftp.gnutls.org/pub/gnutls http://www.mirrors.wiretapped.net/security/network-security/gnutls/
1222 ftp://ftp.gnutls.org/pub/gnutls ftp://ftp.mirrors.wiretapped.net/pub/security/network-security/gnutls/
1223 ftp://ftp.gnutls.org/pub/gnutls http://josefsson.org/gnutls/releases/
1224 http://ftp.info-zip.org/pub/infozip/src/ http://mirror.switch.ch/ftp/mirror/infozip/src/
1225 http://ftp.info-zip.org/pub/infozip/src/ ftp://sunsite.icm.edu.pl/pub/unix/archiving/info-zip/src/
1226 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.cerias.purdue.edu/pub/tools/unix/sysutils/lsof/
1227 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.tau.ac.il/pub/unix/admin/
1228 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.cert.dfn.de/pub/tools/admin/lsof/
1229 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.fu-berlin.de/pub/unix/tools/lsof/
1230 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.kaizo.org/pub/lsof/
1231 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.tu-darmstadt.de/pub/sysadmin/lsof/
1232 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://ftp.tux.org/pub/sites/vic.cc.purdue.edu/tools/unix/lsof/
1233 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://gd.tuwien.ac.at/utils/admin-tools/lsof/
1234 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://sunsite.ualberta.ca/pub/Mirror/lsof/
1235 ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/  ftp://the.wiretapped.net/pub/security/host-security/lsof/
1236 http://www.apache.org/dist  http://archive.apache.org/dist
1237
1238 }
1239