Windows: changelog prior to branching openafs-devel-1_7_x
[openafs.git] / doc / txt / winnotes / afs-integration.txt
1 This document is current as of release 1.6.0b.  It has not been updated
2 to reflect the changes due to the use of the AFSRedir.sys file system
3 redirector driver in 1.7.0100 and later.
4
5 How to determine if OpenAFS is installed?
6
7 When the OpenAFS Client Service is installed there will be several 
8 registry keys created:
9
10   HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon
11      "ImagePath" = "path to afsd_service.exe"
12
13   HKLM\SOFTWARE\TransarcCorporation\AFS Client\CurrentVersion
14      "PathName" = "the path to the client installation directory"
15      "MajorVersion" 
16      "MinorVersion"
17      "VersionString"
18
19 BOOL IsAFSServerInstalled (void)
20 {
21    BOOL fInstalled = FALSE;
22    TCHAR szKey[] = TEXT("HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon");
23    LPCTSTR pch = lstrchr (szKey, TEXT('\\'));
24    HKEY hk;
25    
26    if (RegOpenKey (HKEY_LOCAL_MACHINE, &pch[1], &hk) == 0)
27    {
28       fInstalled = TRUE;
29       RegCloseKey (hk);
30    }
31
32    return fInstalled;
33 }
34
35 How to determine if OpenAFS is active?
36
37 The AFS Client Service is normally started automatically at system boot.
38 The state of the service may be queried by asking the Windows Service 
39 Manager.
40
41 BOOL IsAFSServiceRunning (void)
42 {
43     SERVICE_STATUS Status;
44     memset (&Status, 0x00, sizeof(Status));
45     Status.dwCurrentState = SERVICE_STOPPED;
46
47     SC_HANDLE hManager;
48     if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
49     {
50         SC_HANDLE hService;
51         if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
52         {
53             QueryServiceStatus (hService, &Status);
54             CloseServiceHandle (hService);
55         }
56         CloseServiceHandle (hManager);
57     }
58     return (Status.dwCurrentState == SERVICE_RUNNING);
59 }
60
61 How to determine the AFS UNC Service Name?
62
63 The local UNC service name registered by the OpenAFS Client Service SMB/CIFS 
64 Server depends on whether or not a Microsoft Loopback Adapter has been 
65 installed and the contents of a registry value.  The loopback adapter is 
66 important because if the service cannot bind itself to a loopback adapter 
67 then the registered SMB/CIFS service name must be unique to the WINS name
68 space.  When the loopback adapter is installed, a globally common name such
69 as "AFS" can be used.
70
71 If the loopback adapter is installed the UNC server name will be the value at:
72
73   HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters
74     REG_SZ/REG_EXPAND_SZ  "NetbiosName"
75
76 If this value is not present, the default is "AFS".
77
78 When the loopback adapter is not installed the UNC name will be:
79
80   %COMPUTERNAME%-%NetbiosName%
81
82 if the Computer Name is "MYHOST" and the Netbios Name is "AFS" then
83 the UNC server name will be: 
84
85   MYHOST-AFS
86
87 At the moment there is no readily available code exported by a library to 
88 determine if the loopback adapter is installed or not.  What I will do if
89 someone requests it is add a new AFS pioctl operation which will return
90 the in use UNC Server Name.
91
92
93 How to determine the AFS unix mount point path?
94
95 On Unix systems the local mount point of the AFS file system is usually "/afs".
96 Some organizations have their own custom local mount point locations.  To 
97 determine what the locally configured unix mount point is for interpretting
98 Unix style paths there is a registry value:
99
100   HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters
101     REG_SZ "MountRoot"
102
103 If this value does not exist the default value is "/afs".
104
105 What are AFS pioctl() operations and how do I call them?
106
107 AFS pioctl() operations are IPCs which can be used to communicate with the
108 AFS Client Service for the purposes of querying or changing the state of
109 the service.
110
111 The pioctl() function has a prototype of:
112
113 struct ViceIoctl {
114     long in_size;
115     long out_size;
116     void *in;
117     void *out;
118 };
119
120 long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow);
121
122 and can be loaded from the library "afsauthent.dll" at runtime.  The default
123 calling convention is used.
124
125
126 How to test to see if a PATH is within AFS?
127
128 Given an arbitrary file path, you can test to see if the path is in the AFS
129 file system with the following function.  It asks the AFS Client Service to 
130 return the name of the cell in which the path exists.  If the cell name cannot
131 be found, the path is not in the AFS file space.
132
133 BOOL IsPathInAFS(const CHAR *strPath)
134 {
135     struct ViceIoctl blob;
136     char cellname[256];
137     int code;
138
139     blob.in_size = 0;
140     blob.out_size = sizeof(cellname);
141     blob.out = cellname;
142
143     code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
144     if (code)
145         return FALSE;
146     return TRUE;
147 }
148
149
150 What are AFS cells, volumes and mount points?
151
152 The AFS file system consists of a series of administrative domains called 
153 "cells" each of which contain two or more volumes.  A volume is a file system
154 unit which contains files, directories, mount points, symlinks and hard
155 links.
156
157 Each cell has a minimum of two volumes.  When an AFS client connects to a 
158 cell it mounts the cell's "root.afs" volume at the local afs mount point path.
159 Each "root.afs" volume contains one or more mount points which allow the 
160 AFS client to other volumes in both in the current cell as well as other 
161 cells.  There are two types of mount points: read-only and read-write.  
162 By following a read-only mount point the client can obtain data from any
163 of the equivalent read-only volume replicas.  By following a read-write mount
164 point the client is restricted to the one and only read-write copy of the
165 volume.  Periodically replicated volumes have their read-write copy "released"
166 which results in a synchronization with the read-only copies.
167
168 By convention the first volume of every cell to contain real data is called 
169 "root.cell".  The name of the read-only mount point which joins the "root.afs"
170 volume to the "root.cell" volume is the name of the cell.  The name of the 
171 read-write mount point is the name of the cell prefaced by a dot.  For 
172 example, the "athena.mit.edu" cell's "root.afs" volume will contain mount points
173 such as
174
175         "athena.mit.edu"  -> "#athena.mit.edu:root.cell" 
176         ".athena.mit.edu" -> "%athena.mit.edu:root.cell" 
177
178 The '#' indicates a read-only mount point and the '%' indicates a read-write 
179 mount point.  The mount points are not limited to the local cell so additional 
180 mount points might be included such as:
181
182         "andrew.cmu.edu" -> "#andrew.cmu.edu:root.cell" 
183         "sipb.mit.edu"   -> "#sipb.mit.edu:root.cell"
184
185 The mount points appear as directory entries to the operating system.
186
187 Volumes can also store files, hard links to files, and symlinks to files.  
188
189 On Windows, hardlinks can be created and destroyed using the CreateHardLink() 
190 and DeleteFile() Win32 APIs.  
191
192 Creating, Listing and Destroying symlinks and mount points is performed by
193 the user via the OpenAFS provided command line tools: fs.exe and symlink.exe.
194  
195   symlink make <name> <to>
196   symlink list <name>
197   symlink rm <name>
198
199   fs mkmount <dir> <vol> [<cell>] [-rw]
200   fs lsmount <dir>+
201   fs rmmount <dir>+
202
203 These operations are performed via pioctl calls. 
204
205
206
207 BOOL WhichCell(const char *strPath, char *cell, int len)
208 {
209     struct ViceIoctl blob;
210     int code;
211
212     blob.in_size = 0;
213     blob.out_size = len
214     blob.out = cell;
215
216     code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
217     if (code)
218         return FALSE;
219     return TRUE;
220 }
221
222
223 BOOL WorkstationCell(char *cell, int len)
224 {
225     struct ViceIoctl blob;
226     int code;
227
228     blob.in_size = 0;
229     blob.out_size = len
230     blob.out = cell;
231
232     code = pioctl(NULL, VIOC_GET_WS_CELL, &blob, 1);
233     if (code)
234         return FALSE;
235     return TRUE;
236 }
237
238 /* from afs/afsint.h */
239 struct VolumeStatus {
240         afs_int32 Vid;
241         afs_int32 ParentId;
242         char Online;
243         char InService;
244         char Blessed;
245         char NeedsSalvage;
246         afs_int32 Type;
247         afs_int32 MinQuota;
248         afs_int32 MaxQuota;
249         afs_int32 BlocksInUse;
250         afs_int32 PartBlocksAvail;
251         afs_int32 PartMaxBlocks;
252 };
253 typedef struct VolumeStatus VolumeStatus;
254
255 BOOL WhichVolume(const char *strPath, DWORD * volID, char *volname, int len)
256 {
257     struct ViceIoctl blob;
258     char space[2048];
259     struct VolumeStatus *status;
260     char *name, *offmsg, *motd;
261
262     int code;
263
264     blob.in_size = 0;
265     blob.out_size = sizeof(space);
266     blob.out = space;
267
268     code = pioctl(strPath, VIOCGETVOLSTAT, &blob, 1);
269     if (code)
270         return FALSE;
271
272     status = (VolumeStatus *)space;
273     name = (char *)status + sizeof(*status);
274     offmsg = name + strlen(name) + 1;
275     motd = offmsg + strlen(offmsg) + 1;
276
277     if (volID)
278         *volID = status->Vid;
279
280     if (volname) {
281         strncpy(volname, name, len);
282         volname[len-1] = '\0';
283     }
284
285     /* Other items you could grab if you wanted 
286      *    if (*offmsg) 
287      *    then there is a message explaining why the volume is offline
288      *
289      *    if (*motd) 
290      *    then there is a message of the day.  (very rarely used)
291      *
292      *    status->MaxQuota: 0 is unlimited; otherwise 32-bit number of Blocks
293      *    status->BlocksInUse: 32-bit number of blocks
294      *    status->PartBlocksAvail: 32-bit number of blocks available in
295      *         the partition the volume is located on
296      *    status->PartMaxBlocks: 32-bit number representing the actual size
297      *         of the partition.
298      *
299      * These can be used to compute Quota Used, Partition Used, Space Avail, 
300      * etc.   A block is 1K.
301      *
302      *    status->Type         0=ReadOnly; 1=ReadWrite
303      *    status->Online       (boolean)
304      *    status->InService    (boolean)
305      *    status->Blessed      (boolean)
306      *    status->NeedsSalvage (boolean)
307      *    status->ParentId     Volume ID of the parent volume.  (for readonly)
308      */
309     return TRUE;
310 }
311
312 BOOL IsSymlink(const char * dir, const char * entry) 
313 {
314     struct ViceIoctl blob;
315     char space[2048];
316     int code;
317
318     blob.in_size = strlen(entry);
319     blob.in = entry;
320     blob.out_size = sizeof(space);
321     blob.out = space;
322
323     memset(space, 0, sizeof(space));
324
325     code = pioctl(dir, VIOC_LISTSYMLINK, &blob, 1);
326     if (code)
327         return FALSE;
328
329     return TRUE;
330 }
331
332 BOOL GetSymlink(const char * dir, const char * entry, char * dest, int len) 
333 {
334     struct ViceIoctl blob;
335     char space[2048];
336     int code;
337
338     blob.in_size = strlen(entry);
339     blob.in = entry;
340     blob.out_size = sizeof(space);
341     blob.out = space;
342
343     memset(space, 0, sizeof(space));
344
345     code = pioctl(dir, VIOC_LISTSYMLINK, &blob, 1);
346     if (code)
347         return FALSE;
348
349     strncpy(dest, space, len);
350     dest[len-1] = '\0';
351     return TRUE;
352 }
353
354 BOOL IsMountPoint(const char * dir, const char * entry)
355 {
356     struct ViceIoctl blob;
357     char space[2048];
358     int code;
359
360     blob.in_size = strlen(entry);
361     blob.in = entry;
362     blob.out_size = sizeof(space);
363     blob.out = space;
364
365     memset(space, 0, sizeof(space));
366
367     code = pioctl(dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
368     if (code)
369         return FALSE;
370
371     return TRUE;
372 }
373
374 BOOL GetMountPoint(const char * dir, const char * entry, char * dest, int len)
375 {
376     struct ViceIoctl blob;
377     char space[2048];
378     int code;
379
380     blob.in_size = strlen(entry);
381     blob.in = entry;
382     blob.out_size = sizeof(space);
383     blob.out = space;
384
385     memset(space, 0, sizeof(space));
386
387     code = pioctl(dir, VIOC_AFS_STAT_MT_PT, &blob, 1);
388     if (code)
389         return FALSE;
390
391     strncpy(dest, space, len);
392     dest[len-1] = '\0';
393     return TRUE;
394 }
395
396 BOOL IsOnline(const char *strPath)
397 {
398     struct ViceIoctl blob;
399     char space[2048];
400     struct VolumeStatus *status;
401     int code;
402
403     blob.in_size = 0;
404     blob.out_size = sizeof(space);
405     blob.out = space;
406
407     code = pioctl(strPath, VIOCGETVOLSTAT, &blob, 1);
408     if (code)
409         return FALSE;
410
411     status = (VolumeStatus *)space;
412
413     if (!status->Online ||
414         !status->InService ||
415         !status->Blessed ||
416         status->NeedsSalvage)
417         return FALSE;
418
419     return TRUE;
420 }