1 /* ipc.cc: Single unix specification IPC interface for Cygwin
3 Originally written by Robert Collins <robert.collins@hotmail.com>
4 Updated to 64 bit key_t by Charles Wilson <cygwin@cwilson.fastmail.fm>
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
15 /* Notes: we return a valid key even if id's low order 8 bits are 0. */
17 ftok (const char *path
, int id
)
21 if (stat (path
, &statbuf
))
23 /* stat set the appropriate errno for us */
28 dev_t is 32bits for cygwin
29 ino_t is 64bits for cygwin
30 and we need 8 bits for the id.
31 thus key_t needs 104 bits total -- but we only have 64 (long long)
32 We will have to alias; leaving open the possibility that the same
33 key will be returned for multiple files. This possibility exists
34 also on Linux; the question is, how to minimize this possibility.
36 How to solve? Well, based on C. Vinschen's research, the nFileIndex*
37 words vary as follows, on a partition with > 110,000 files
38 nFileIndexHigh: 564 values between 0x00010000 -- 0xffff0000
39 nFileIndexLow : 103812 values between 0x00000000 -- 0x0003ffff
40 R. Collins suggests that these may represent a tree path,
41 and that it would require ~2.9M files to force the tree depth
42 to increase and reveal more bit usage.
44 Implementation details: dev_t is 32bits, but is formed by
45 device(32bits) << 16 | unit(32bits)
46 But device is ACTUALLY == status & FH_DEVMASK, where FH_DEVMASK
47 is 0x00000fff --> 12 bits
49 As it happens, the maximum number of devices is actually
50 FH_NDEV, not FH_DEVMASK, where FH_NDEV is currently 0x0000001d.
51 However, FH_NDEV grows as new device types are added. So
52 currently the device number needs 5 bits, but later? Let's
53 take a cue from Linux, and use the lower 8 bits (instead of the
54 lower 12 or 16) for the device (major?) number.
56 Similarly, while 'units' is an int (32bits), it is unclear
57 how many of these are significant. For most devices, it seems that
58 'units' is equivalent to 'minor'. For FH_TAPE, it's obvious that
59 only 8 bits are important. However, for FH_SOCKET...it might be
60 as high as 16 significant bits.
62 Let's assume that we only need 8 bits from device (major) and
63 only 8 bits from unit (minor). (On linux, only 8 bits of minor
64 are used, and none from major).
65 ---> so, we only need 0x00ff00ff (16 bits) of dev_t
67 ---> we MUST have all 8 bits of id.
69 ---> So, we only have 64 - 8 - 16 = 40 bits for ino_t. But, we
70 need 0xffff0000 for nFileIndexHigh and 0x0003ffff for nFileIndexLow
71 minimum, or 16 + 18 = 34 bits. Lucky us - we have 6 more bits
74 For lack of a better idea, we'll allocate 2 of the extra bits to
75 nFileIndexHigh and 4 to nFileIndexLow. */
77 /* get 8 bits from dev_t (major), put into 0xff00000000000000L */
78 tmp
= (((key_t
) statbuf
.st_dev
) & 0x0000000000ff0000LL
) << 40;
79 /* get 8 bits from dev_t (minor), put into 0x00ff000000000000L */
80 tmp
|= (((key_t
) statbuf
.st_dev
) & 0x00000000000000ffLL
) << 48;
81 /* get upper 16+2 bits from nFileInfoHigh, put into 0x0000ffffc0000000L
82 shift down first, then mask, to avoid sign extension on rightshift */
83 tmp
|= (((key_t
) statbuf
.st_ino
) & 0xffffc00000000000LL
) >> 16;
84 /* get lower 18+4 bits from nFileInfoLow, put into 0x000000003fffff00L */
85 tmp
|= (((key_t
) statbuf
.st_ino
) & 0x00000000003fffffLL
) << 8;
86 /* use all 8 bits of id, and put into 0x00000000000000ffL */