freebsd/portupgrade — pull request #56 by yasuhirokimura (2014-03-16 16:09:33+00:00)
Title: Use temporarily generated file name as the argument of 'make index'.

'portsdb -U' recreates INDEX file by running 'make index', and it is done by following steps:

1. Run 'make INDEXFILE=INDEX.tmp index', which takes following substeps:
a. Create temporary directory under /tmp (= /tmp/index.????????).
b. For each category file named INDEX.tmp.desc.${category} is created under the directory of step a, and output of 'make describe' for all ports belonging to the category is written to the file.
c. All contents of /tmp/index.????????/INDEX.tmp.desc.* are merged and written to ${PORTSDIR}/INDEX.tmp.tmp.
d. ${PORTSDIR}/INDEX.tmp.tmp is moved to ${PORTSDIR}/INDEX.tmp.
e. Temporary directory created at step a is removed.
2. Temporary file path is genarated by calling 'Tempfile.new('INDEX')' (= /tmp/INDEX????????-?????-??????), and ${PORTSDIR}/INDEX.tmp, created by step 1, is moved to it.
3. File created by step 2 is moved to ${PORTSDIR}/INDEX-${OSMajorVersion} (${PORTSDIR}/INDEX-10 for example).

By the way we assume following situation:

* There are 3 FreeBSD clients.
* OS major version of each client is different (e.g. 8.4-RELEASE, 9.2-RELEASE and 10.0-RELEASE)
* There is one port tree on file server and each client mounts it on their /usr/port. i.e., all clients share ${PORTSDIR}.

And also assume we want to recreate INDEX-{8,9,10} and have run 'portsdb -U' on each client at same time. Let's consider what may happen.

* At step 1-a, 1-b and 2 file or directory are created under local /tmp directory of each client. No problem.
* At step 1-e files and directory under local /tmp directory of each client are removed. No problem.
* At step 3 file is created under shared /usr/ports directory, but file name is different between each client (INDEX-8, INDEX-9 and INDEX-10). No problem.
* At step 1-c and 1-d file is created under shared /usr/ports directory, and this time file name is same between each client. So two or more clients may write or move to same file simultaneously.

Therefore if timing is bad 'portsdb -U' on each client may fail because of file path conflict.

This patch fixes such problem by changing step 1 as following:

* Generate temporary file path by calling 'Tempfile.new('INDEX.', '/usr/ports')' (= /usr/ports/INDEX????????-?????-??????)
* Use this file name (= INDEX????????-?????-??????) as argument of 'make index'. i.e. 'make INDEXFILE=INDEX????????-?????-??????'.