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