***************************************************************************** * INTERPRETING A DIFF OUTPUT * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.1) * ***************************************************************************** The diff command with the -ruN options compares two file subtrees and creates a patch file that lists the differences between the subtrees. We'll show on a specific example how to interpret the patch file produced by diff. ***************************************************************************** SCENARIO: we are interested in checking the differences between the linux-2.2.13 and the linux-2.2.14 file subtrees. First we must issue a make distclean command in both directories to remove all non-text files. Now we are ready to issue the following command: ***************************************************************************** diff -ruN linux-2.2.13 linux-2.2.14 > /tmp/patch-2.2.14 ***************************************************************************** COMMAND EXECUTION: since the -r recursive option is set, diff examines all directories and files in the two linux folders. The -N option specifies that if a file is present in a directory, it must be considered as present, although empty, in the corresponding directory. The -u option specifies that the unified output format is used. For each file considered, diff prints a line such as: ***************************************************************************** diff -ruN linux-2.2.13/arch/i386/kernel/signal.c linux-2.2.14/arch/i386/kernel/signal.c The first subtree name, linux-2.2.13, is the reference subtree. All differences found in the linux-2.2.14 subtree are relative to the first subtree. ***************************************************************************** DIFF HEADER: diff records first the creation dates of the two files: ***************************************************************************** *** linux-2.2.13/arch/i386/kernel/signal.c Tue Jun 8 01:14:20 1999 --- linux-2.2.14/arch/i386/kernel/signal.c Sun Jan 23 17:29:25 2000 ***************************************************************************** DIFF BODY: diff detects then three kinds of differences between the two files: a) addition: a line not present in the old file has been added to the new file b) replacement: consecutive lines of the old file line have been replaced by other consecutive lines in the new file c) deletion: a line of the old file is no longer present in the new file. In each case, line numbers to which the changes apply are produced. Let us describe the notation used by diff to distinguish the three cases. ***************************************************************************** ADDITION: the patch lines (relative to the old and new versions of the arch/i386/kernel/signal.c file) *** 419,431 **** --- 419,437 ---- ? current->exec_domain->signal_invmap[sig] : sig), &frame->sig); + if (err) + goto give_sigsegv; specify that two new lines identified by the + character have been added in the new file right after the &frame->sig); line. The *** 419,431 **** patch line is not strictly necessary: it informs the user that the changes refer to lines 419-431 of the old file, while the --- 419,437 ---- line tells that the changes refer to lines 419-437 of the new file. REPLACEMENT: the patch lines (relative to the old and new versions of the arch/i386/kernel/smp.c file) *************** *** 367,377 **** printk("I/O APIC #%d Version %d at 0x%lX.\n", m->mpc_apicid,m->mpc_apicver, m->mpc_apicaddr); ! /* ! * we use the first one only currently ! */ ! if (ioapics == 1) ! mp_ioapic_addr = m->mpc_apicaddr; } mpt+=sizeof(*m); count+=sizeof(*m); followed by the lines: --- 368,376 ---- printk("I/O APIC #%d Version %d at 0x%lX.\n", m->mpc_apicid,m->mpc_apicver, m->mpc_apicaddr); ! mp_apics [mp_apic_entries] = *m; ! if (++mp_apic_entries > MAX_IO_APICS) ! --mp_apic_entries; } mpt+=sizeof(*m); count+=sizeof(*m); specify that the five lines of the old file identified by the ! character have been replaced in the new file by the three lines identified by the ! character. DELETION: the patch lines (relative to the old and new versions of the drivers/net/Config.in file) *************** *** 93,100 **** fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139 - tristate 'SiS 900 PCI Fast Ethernet Adapter support' CONFIG_SIS900 - tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN fi bool 'Other ISA cards' CONFIG_NET_ISA if [ "$CONFIG_NET_ISA" = "y" ]; then --- 94,99 ---- *************** specify that the two lines of the old file identified by the - character are no longer present in the new file. ***************************************************************************** * MAKING A PRIVATE PATCH * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.1) * ***************************************************************************** You have modified and tested a new version of Linux, say Linux-2.4.5kh3, which differs a little from the previous version, say Linux-2.4.5kh2, you are currently using. You are now going to produce a "patch" that will transform Linux-2.4.5kh2 (the old kernel) into Linux-2.4.5kh3 (the new kernel). Needless to say, the size of a patch is much smaller than the size of a linux kernel. The patch usually fits in a single diskette. It is thus quite useful to update the old kernel in some other computer. So we are essentially describing a two-step process: a) Produce a patch file on computer A (the one that contains the source code of both the old kernel and the new kernel) and copy it on a floppy. b) Move to computer B, read the floppy containing the patch and update the old kernel of computer B into a new kernel Steps 1-4 describe how to produce a patch file and copy it on a diskette. Steps 5-6 describe how to make use of the patch file to update the old kernel into a new one. ***************************************************************************** STEP 1: Clean up the two kernel sources (no *.o or .* files) ***************************************************************************** Assume that the pathnames of the two kernel sources are: /usr/src/linux-2.4.5kh2 and: /usr/src/linux-2.4.5kh3 Run the following commands: cd /usr/src/linux-2.4.5kh2 make distclean cd /usr/src/linux-2.4.5kh3 make distclean ***************************************************************************** STEP 2: Produce a "context diffs" file between the two kernel sources ***************************************************************************** Run the following commands (first the old kernel, then the new one): cd /usr/src diff -ruN linux-2.4.5kh2 linux-2.4.5kh3 > patch-2.4.5kh3 ***************************************************************************** STEP 3: Check the patch file ***************************************************************************** Run the following command to check whether the diff file does not include any garbage: less patch-2.4.5kh3 If the patch file includes non text code, repeat steps 1-3 ***************************************************************************** STEP 4: Copy the patch file on a diskette ***************************************************************************** mount /flp cp /usr/src/patch-2.4.5kh3 /flp umount /flp Since our patches are usually small, we don't need to compress them. We now move to computer B with our floppy containing the patch. ***************************************************************************** STEP 5: Read the patch file from the diskette ***************************************************************************** cd /usr/src mount /flp cp /flp/patch-2.4.5kh3 patch-2.4.5kh3 umount /flp ***************************************************************************** STEP 6: Patch the old kernel with the patch file obtaining the new kernel ***************************************************************************** a) execute the wonderful patch command: patch -p0 < patch-2.4.5kh3 The patch command acts on the input patch-2.4.5kh3 patch file and updates correspondingly all files and directories of the old source code to which diff was applied (in our example, the old kernel source is linux-2.4.5kh2). The -p0 option leaves the file names unchanged (no prefix / removed from file names). b) rename the kernel: mv linux-2.4.5kh2 linux-2.4.5kh3 ***************************************************************************** Undoing a patch ***************************************************************************** You are not satisfied, for some reason, by the patch just made and you want to go back to the earlier version of the kernel (of course, you could save a version of the old kernel before making the patch but this requires a lot of disk space and a lot of time). For sake of concreteness, let us suppose we want to undo the actions performed in step 6. Then we proceed as follows: a) set the name of the kernel version to the previous version: mv linux-2.4.5kh3 linux-2.4.5kh2 b) execute the wonderful patch command: patch -RE -p0 < patch-2.4.5kh3 The -E option removes empty files while the -R option specifies that the role of the old and new file appearing in the patch file must be swapped. ***************************************************************************** Avoiding doing a make distclean ***************************************************************************** As described in /usr/src/linux/Documentation/SubmittingPatches, to run a recursive diff without making distclean, use: diff -ruN -X dontdiff linux-2.4.5kh2 linux-2.4.5kh3 > patch.diff where dontdiff is the exclude file downloadable from: http://www.moses.uklinux.net/patches/dontdiff ***************************************************************************** * MAKING AN OFFICIAL KERNEL PATCH * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.1) * ***************************************************************************** You have installed the new Linux, say Linux-2.4.2. Roughly once every month, new Linux patches are introduced to fix some bugs and/or to support new device drivers and new features. So a few months after you have installed Linux-2.4.2, the new stable release is, say, Linux-2.4.5. The procedure we are going to describe explains how you can update your Linux 2.4.2 version into the more recent Linux-2.4.5 with a relatively small effort. The trick consists in using a series of patch files. ***************************************************************************** STEP 0: Understanding how official Linux patch files are made ***************************************************************************** Each official Linux patch file is a diff file that includes all the differences between two consecutive Linux version. Let us consider, as an example, the patch that transforms linux-2.4.2 into linux-2.4.3. Such patch has been obtained in the following way: cd /usr/src/linux-2.4.2 make distclean cd /usr/src/linux-2.4.3 make distclean ln -s linux-2.4.2 linux diff -ruN linux linux-2.4.3 > patch_2.4.3 gzip patch_2.4.3 The patch is gzipped in order to reduce the download time from linux distribution sites. The resulting patch, called patch_2.4.3.gz, is thus a compressed diff file. Linux official patches assume that the reference subtree is always "linux". This approach is a bit confusing but it allow several consecutive patches to be applied consecutively without renaming the reference subtree (see next). The names of these patch files are standard so: patch_2.4.3 contains the differences between linux-2.4.3 and linux-2.4.2 patch_2.4.4 contains the differences between linux-2.4.4 and linux-2.4.3 patch_2.4.5 contains the differences between linux-2.4.5 and linux-2.4.4 and so forth. In our example, we are going to need precisely the three compressed patch files, namely: patch_2.4.3.gz, patch_2.4.4.gz, and patch_2.4.5.gz, to transform Linux-2.4.2 into Linux-2.4.5. ***************************************************************************** STEP 1: Update the name of the linux source code directory and the linux symbolic link ***************************************************************************** Assume that the pathnames of the kernel source is: /usr/src/linux-2.4.2/ and that all the required compressed patch files are already included in the /usr/src directory. execute the following commands: cd /usr/src mv linux-2.4.2 linux-2.4.5 rm linux ln -s linux-2.4.5 linux ***************************************************************************** STEP 2: Clean the source code directory (remove object and configuration files) ***************************************************************************** execute the following command: cd linux make distclean ***************************************************************************** STEP 3: Unzip the patch files ***************************************************************************** in our example, execute: cd /usr/src gunzip patch-2.4.3.gz gunzip patch-2.4.4.gz gunzip patch-2.4.5.gz ***************************************************************************** STEP 4: Execute repeatedly the patch command ***************************************************************************** execute the following commands: for i in 3 4 5; do patch -p0 < patch_2-4.$i done What does this combined command do? The: patch -p0 < patchfile command acts on the input patch file and updates correspondingly all files and directories of all kernel source to which diff was applied (in our example, the old kernel source is /usr/src/linux). The -p0 option leaves the file names unmodified (no prefix / removed from file names). The target directory is linux, that is, the old kernel source. As a result, the old kernel source is updated into the new kernel source.