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