2

I am a new Linux user learning from Arch Linux and recently Linux From Scratch (7.7). I set up a new installation of AL to be my LFS host; I manually (and also with the provided bash script) checked prerequisite packages on my host. In my case, I am confident I resolved all discrepancies except for linking /usr/bin/yacc to /usr/bin/bison.

The provided script results in yacc is bison (GNU Bison) 3.0.4, as opposed to /usr/bin/yacc -> /usr/bin/bison. Because the latter was the output format for checked symbolic links, I assumed the script was telling me yacc is prepared but employing a different kind of link. I investigated more about Linux file systems and took away a cursory understanding that actual data is described by inodes (metadata), which are in turn pointed to by the (abstract) files we interact with. Files that simply point to the same inode are considered hard links (although, I think the files are independent of each other). I ran sudo ls -il /usr/bin | less and found yacc and bison had slightly different inode numbers (152077 and 152078, respectively). Does this mean they are not hard linked, or am I misinterpreting the script output and require a fix?

Edit: Relevant commands from bash script:

bison --version | head -n1

if [ -h /usr/bin/yacc ]; then
  echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
elif [ -x /usr/bin/yacc ]; then
  echo yacc is `/usr/bin/yacc --version | head -n1`
else
  echo "yacc not found" 
fi
2

When you did the ls -il /usr/bin, you were listing file names and matching inode numbers. In this context, it's probably best to think of "file name" as separate from "inode", and to think of the inode as the file.

The "inode" is typically an on-disk data structure containing metadata (permissons, ownership, creation time, access time, etc) and the disk blocks that contain the file's data. Depending on the file system, inodes can be located strategically around the disk, or live in a database of sorts. Most of the time, there's a fast algorithm to go from inode number to the disk block the inode is in, so that lookup is quite rapid.

From this standpoint, every file name is just a "hard link". A directory just matches up file names and inode numbers. No distinction is made between a "real file name" and a "hard link". So your file names /usr/bin/yacc and /usr/bin/bison are matched to different inode numbers means that those two names refer to different metadata, and different file data. Speaking casually, the files are not hard links in the sense that only one file name matches each of the two inodes, but from a technical sense, both file names are hard links, they're each just the single hard link to the inode.

As far as your script and the "almost identical inode numbers", yacc and bison are related. On my Arch laptop:

1032 % ls -li /usr/bin/yacc /usr/bin/bison
1215098 -rwxr-xr-x 1 root root 394152 Jan 23  2015 /usr/bin/bison*
1215097 -rwxr-xr-x 1 root root     41 Jan 23  2015 /usr/bin/yacc*
1033 % file /usr/bin/yacc
/usr/bin/yacc: POSIX shell script, ASCII text executable
1034 % cat /usr/bin/yacc
#! /bin/sh
exec '/usr/bin/bison' -y "$@"

The file names yacc and bison identify inode numbers only one apart, probably because they got created one after the other. The file name for yacc does not represent a symbolic link or a hard link. A symbolic link would show up differently in the ls -li output, two hard links would each represent the same inode number.

But yacc is related to bison in that it's a shell script that invokes bison. That's why your script gives output something like:

bison (GNU Bison) 3.0.4
yacc is bison (GNU Bison) 3.0.4

Your script invokes /usr/bin/yacc which actually just executes /usr/bin/bison.

  • Thank you for your answer @Bruce Ediger! As a new user, it helps to walk in new information. Much of what you described--inodes being one-to-one with file data; hard links being file names mapped to inodes, regardless of other hard links; etc--affirmed my first understanding. You also explained that my files are not mapped to the same inode, and so they are not relatively "hard links" (in the casual phrasing). Do you understand what the script output indicates (I will post the relevant commands in the question)? I am being pedantic and don't want to unnecessarily mess with the files' linking. – Polite Master Aug 2 '15 at 14:57
  • I appreciate your experience with Arch and Linux, @Bruce Ediger. Thank you for clearing it all up. – Polite Master Aug 3 '15 at 5:04
0

If two files have different inode numbers, they aren't hardlinked. That's the definition of hard links — it's the same file (so same metadata including the inode number) at different locations in the filesystem (different names or different directories).

Bison is an implementation of yacc. More precisely, bison -y emulates a POSIX yacc. You can have a different implementation of yacc as /usr/bin/yacc. In your case, it looks like you installed Bison twice, once as /usr/bin/yacc and once as /usr/bin/bison. They may or may not have been built in the same way. Check your build scripts.

In dash, ksh or bash, you can use [ /usr/bin/yacc -ef /usr/bin/bison ] to test whether /usr/bin/yacc and /usr/bin/bison are the same file (i.e. they're chains of symbolic links (possibly of length 0) leading to hard links of the same file).

  • Great, @Gilles! I tried several Google searches on variants of [ -h /usr/bin/yacc ] and if-then-elseif without success. I even tried entering parts of the script into bash to see if I could parse anything about it (I am using a virtual machine with a revertible snapshot). I entered your code and got no output (a new bash prompt). This is different from when I was trying things like if [ -h /usr/bin/yacc ]; then echo foo; else echo bar, which ended up in errors (or in other cases, making bash work on something that did not allow me a new bash prompt). Kindly let me know what no output means. – Polite Master Aug 3 '15 at 5:23
  • @PoliteMaster Like every other use of [ … ], it's a test. You can write if [ /usr/bin/yacc -ef /usr/bin/bison ]; then echo "/usr/bin/yacc and /usr/bin/bison are the same file"; else echo "/usr/bin/yacc and /usr/bin/bison are different files or one of them doesn't exist"; fi – Gilles Aug 3 '15 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.