afsd: include sys/resource.h in afsd_kernel.c
[openafs.git] / src / afsd / afsd_kernel.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #define VFS 1
16
17 #include <afs/cmd.h>
18
19 #include "afsd.h"
20
21 #include <assert.h>
22 #include <afs/afsutil.h>
23 #include <sys/file.h>
24 #include <sys/wait.h>
25
26 #if defined(AFS_LINUX20_ENV)
27 #include <sys/resource.h>
28 #endif
29
30 #ifdef HAVE_SYS_FS_TYPES_H
31 #include <sys/fs_types.h>
32 #endif
33
34 #ifdef HAVE_SYS_MOUNT_H
35 #include <sys/mount.h>
36 #endif
37
38 #ifdef HAVE_SYS_FCNTL_H
39 #include <sys/fcntl.h>
40 #endif
41
42 #ifdef HAVE_SYS_MNTTAB_H
43 #include <sys/mnttab.h>
44 #endif
45
46 #ifdef HAVE_SYS_MNTENT_H
47 #include <sys/mntent.h>
48 #endif
49
50 #ifdef HAVE_MNTENT_H
51 #include <mntent.h>
52 #endif
53
54 #ifdef HAVE_SYS_MOUNT_H
55 #include <sys/mount.h>
56 #endif
57
58 #ifdef HAVE_SYS_VFS_H
59 #include <sys/vfs.h>
60 #endif
61
62 #ifdef HAVE_SYS_FSTYP_H
63 #include <sys/fstyp.h>
64 #endif
65
66 #include <ctype.h>
67
68 #include <afs/opr.h>
69 #include <afs/afs_args.h>
70 #include <afs/cellconfig.h>
71 #include <afs/afssyscalls.h>
72 #include <afs/afsutil.h>
73
74 #ifdef AFS_DARWIN_ENV
75 #ifdef AFS_DARWIN80_ENV
76 #include <sys/xattr.h>
77 #endif
78 #include <mach/mach.h>
79 #ifndef AFS_DARWIN100_ENV
80 /* Symbols from the DiskArbitration framework */
81 kern_return_t DiskArbStart(mach_port_t *);
82 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
83                                                          char *);
84 #define DISK_ARB_NETWORK_DISK_FLAG 8
85 #endif
86 #include <mach/mach_port.h>
87 #include <mach/mach_interface.h>
88 #include <mach/mach_init.h>
89 #endif /* AFS_DARWIN_ENV */
90
91 #ifndef MOUNT_AFS
92 #define MOUNT_AFS AFS_MOUNT_AFS
93 #endif /* MOUNT_AFS */
94
95 #ifdef AFS_SGI65_ENV
96 # include <sched.h>
97 # define SET_RTPRI(P) {  \
98     struct sched_param sp; \
99     sp.sched_priority = P; \
100     if (sched_setscheduler(0, SCHED_RR, &sp)<0) { \
101         perror("sched_setscheduler"); \
102     } \
103 }
104 # define SET_AFSD_RTPRI() SET_RTPRI(68)
105 # define SET_RX_RTPRI()   SET_RTPRI(199)
106 #else
107 # ifdef AFS_LINUX20_ENV
108 #  define SET_AFSD_RTPRI()
109 #  define SET_RX_RTPRI() do { \
110     if (setpriority(PRIO_PROCESS, 0, -10) < 0) \
111         perror("setting rx priority"); \
112 } while (0)
113 # else
114 #  define SET_AFSD_RTPRI()
115 #  define SET_RX_RTPRI()
116 # endif
117 #endif
118
119 void
120 afsd_set_rx_rtpri(void)
121 {
122     SET_RX_RTPRI();
123 }
124
125 void
126 afsd_set_afsd_rtpri(void)
127 {
128     SET_AFSD_RTPRI();
129 }
130
131 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
132
133 int
134 afsd_call_syscall(long param1, long param2, long param3, long param4, long param5,
135              long param6, long  param7)
136 {
137     int error;
138 # ifdef AFS_LINUX20_ENV
139     long eparm[4];
140     struct afsprocdata syscall_data;
141     int fd = open(PROC_SYSCALL_FNAME, O_RDWR);
142     if (fd < 0)
143         fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
144     eparm[0] = param4;
145     eparm[1] = param5;
146     eparm[2] = param6;
147     eparm[3] = param7;
148
149     param4 = (long)eparm;
150
151     syscall_data.syscall = AFSCALL_CALL;
152     syscall_data.param1 = param1;
153     syscall_data.param2 = param2;
154     syscall_data.param3 = param3;
155     syscall_data.param4 = param4;
156     if (fd > 0) {
157         error = ioctl(fd, VIOC_SYSCALL, &syscall_data);
158         close(fd);
159     } else
160 # endif /* AFS_LINUX20_ENV */
161 # ifdef AFS_DARWIN80_ENV
162     struct afssysargs syscall_data;
163     void *ioctldata;
164     int fd = open(SYSCALL_DEV_FNAME,O_RDWR);
165     int syscallnum;
166 #ifdef AFS_DARWIN100_ENV
167     int is64 = 0;
168     struct afssysargs64 syscall64_data;
169     if (sizeof(param1) == 8) {
170         syscallnum = VIOC_SYSCALL64;
171         is64 = 1;
172         ioctldata = &syscall64_data;
173         syscall64_data.syscall = (int)AFSCALL_CALL;
174         syscall64_data.param1 = param1;
175         syscall64_data.param2 = param2;
176         syscall64_data.param3 = param3;
177         syscall64_data.param4 = param4;
178         syscall64_data.param5 = param5;
179         syscall64_data.param6 = param6;
180     } else {
181 #endif
182         syscallnum = VIOC_SYSCALL;
183         ioctldata = &syscall_data;
184         syscall_data.syscall = AFSCALL_CALL;
185         syscall_data.param1 = param1;
186         syscall_data.param2 = param2;
187         syscall_data.param3 = param3;
188         syscall_data.param4 = param4;
189         syscall_data.param5 = param5;
190         syscall_data.param6 = param6;
191 #ifdef AFS_DARWIN100_ENV
192     }
193 #endif
194     if(fd >= 0) {
195         error = ioctl(fd, syscallnum, ioctldata);
196         close(fd);
197     } else {
198         error = -1;
199     }
200     if (!error) {
201 #ifdef AFS_DARWIN100_ENV
202         if (is64)
203             error=syscall64_data.retval;
204         else
205 #endif
206             error=syscall_data.retval;
207     }
208 # elif defined(AFS_SUN511_ENV)
209         {
210             int rval;
211             rval = ioctl_sun_afs_syscall(AFSCALL_CALL, param1, param2, param3,
212                                          param4, param5, param6, &error);
213             if (rval) {
214                 error = rval;
215             }
216         }
217 # else /* AFS_DARWIN80_ENV */
218         error =
219         syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4,
220                 param5, param6, param7);
221 # endif /* !AFS_DARWIN80_ENV */
222
223     if (afsd_debug) {
224 #ifdef AFS_NBSD40_ENV
225         char *s = strerror(errno);
226         printf("SScall(%d, %d, %d)=%d (%d, %s)\n", AFS_SYSCALL, AFSCALL_CALL,
227                 param1, error, errno, s);
228 #else
229         printf("SScall(%d, %d, %ld)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1,
230                error);
231 #endif
232     }
233
234     return (error);
235 }
236 #else /* !AFS_SGI_ENV && !AFS_AIX32_ENV */
237 # if defined(AFS_SGI_ENV)
238 int
239 afsd_call_syscall(call, parm0, parm1, parm2, parm3, parm4)
240 {
241
242     int error;
243
244     error = afs_syscall(call, parm0, parm1, parm2, parm3, parm4);
245     if (afsd_verbose)
246         printf("SScall(%d, %d)=%d ", call, parm0, error);
247
248     return error;
249 }
250 # else /* AFS_SGI_ENV */
251 int
252 afsd_call_syscall(call, parm0, parm1, parm2, parm3, parm4, parm5, parm6)
253 {
254
255     return syscall(AFSCALL_CALL, call, parm0, parm1, parm2, parm3, parm4,
256                    parm5, parm6);
257 }
258 # endif /* !AFS_SGI_ENV */
259 #endif /* AFS_SGI_ENV || AFS_AIX32_ENV */
260
261
262 #ifdef  AFS_AIX_ENV
263 /* Special handling for AIX's afs mount operation since they require much more
264  * miscl. information before making the vmount(2) syscall */
265 #include <sys/vfs.h>
266
267 #define ROUNDUP(x)  (((x) + 3) & ~3)
268
269 aix_vmount(const char *cacheMountDir)
270 {
271     struct vmount *vmountp;
272     int size, error;
273
274     size = sizeof(struct vmount) + ROUNDUP(strlen(cacheMountDir) + 1) + 5 * 4;
275     /* Malloc and zero the vmount structure */
276     if ((vmountp = calloc(1, size)) == NULL) {
277         printf("Can't allocate space for the vmount structure (AIX)\n");
278         exit(1);
279     }
280
281     /* transfer info into the vmount structure */
282     vmountp->vmt_revision = VMT_REVISION;
283     vmountp->vmt_length = size;
284     vmountp->vmt_fsid.fsid_dev = 0;
285     vmountp->vmt_fsid.fsid_type = AFS_MOUNT_AFS;
286     vmountp->vmt_vfsnumber = 0;
287     vmountp->vmt_time = 0;      /* We'll put the time soon! */
288     vmountp->vmt_flags = VFS_DEVMOUNT;  /* read/write permission */
289     vmountp->vmt_gfstype = AFS_MOUNT_AFS;
290     vmountdata(vmountp, "AFS", cacheMountDir, "", "", "", "rw");
291
292     /* Do the actual mount system call */
293     error = vmount(vmountp, size);
294     free(vmountp);
295     return (error);
296 }
297
298 vmountdata(struct vmount * vmtp, char *obj, char *stub, char *host,
299            char *hostsname, char *info, char *args)
300 {
301     struct data {
302         short vmt_off;
303         short vmt_size;
304     } *vdp, *vdprev;
305     int size;
306
307     vdp = (struct data *)vmtp->vmt_data;
308     vdp->vmt_off = sizeof(struct vmount);
309     size = ROUNDUP(strlen(obj) + 1);
310     vdp->vmt_size = size;
311     strcpy(vmt2dataptr(vmtp, VMT_OBJECT), obj);
312
313     vdprev = vdp;
314     vdp++;
315     vdp->vmt_off = vdprev->vmt_off + size;
316     size = ROUNDUP(strlen(stub) + 1);
317     vdp->vmt_size = size;
318     strcpy(vmt2dataptr(vmtp, VMT_STUB), stub);
319
320     vdprev = vdp;
321     vdp++;
322     vdp->vmt_off = vdprev->vmt_off + size;
323     size = ROUNDUP(strlen(host) + 1);
324     vdp->vmt_size = size;
325     strcpy(vmt2dataptr(vmtp, VMT_HOST), host);
326
327     vdprev = vdp;
328     vdp++;
329     vdp->vmt_off = vdprev->vmt_off + size;
330     size = ROUNDUP(strlen(hostsname) + 1);
331     vdp->vmt_size = size;
332     strcpy(vmt2dataptr(vmtp, VMT_HOSTNAME), hostsname);
333
334
335     vdprev = vdp;
336     vdp++;
337     vdp->vmt_off = vdprev->vmt_off + size;
338     size = ROUNDUP(strlen(info) + 1);
339     vdp->vmt_size = size;
340     strcpy(vmt2dataptr(vmtp, VMT_INFO), info);
341
342     vdprev = vdp;
343     vdp++;
344     vdp->vmt_off = vdprev->vmt_off + size;
345     size = ROUNDUP(strlen(args) + 1);
346     vdp->vmt_size = size;
347     strcpy(vmt2dataptr(vmtp, VMT_ARGS), args);
348 }
349 #endif /* AFS_AIX_ENV */
350
351 #ifdef  AFS_HPUX_ENV
352 #define MOUNTED_TABLE   MNT_MNTTAB
353 #else
354 #define MOUNTED_TABLE   MOUNTED
355 #endif
356
357 static int
358 HandleMTab(char *cacheMountDir)
359 {
360 #if (defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV))
361     FILE *tfilep;
362 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
363     struct mntent tmntent;
364     char *dir;
365     int i;
366
367     tfilep = setmntent("/etc/mtab", "a+");
368     if (!tfilep) {
369         printf("Can't open /etc/mtab for writing (errno %d); not adding "
370                "an entry for AFS\n", errno);
371         return 1;
372     }
373
374     dir = strdup(cacheMountDir);
375
376     /* trim trailing slashes; don't look at dir[0] in case we are somehow
377      * just "/" */
378     for (i = strlen(dir)-1; i > 0; i--) {
379         if (dir[i] == '/') {
380             dir[i] = '\0';
381         } else {
382             break;
383         }
384     }
385
386     tmntent.mnt_fsname = "AFS";
387     tmntent.mnt_dir = dir;
388     tmntent.mnt_type = "afs";
389     tmntent.mnt_opts = "rw";
390     tmntent.mnt_freq = 1;
391     tmntent.mnt_passno = 3;
392     addmntent(tfilep, &tmntent);
393     endmntent(tfilep);
394
395     free(dir);
396     dir = NULL;
397 #else
398     struct mntent tmntent;
399
400     memset(&tmntent, '\0', sizeof(struct mntent));
401     tfilep = setmntent(MOUNTED_TABLE, "a+");
402     if (!tfilep) {
403         printf("Can't open %s for write; Not adding afs entry to it\n",
404                MOUNTED_TABLE);
405         return 1;
406     }
407     tmntent.mnt_fsname = "AFS";
408     tmntent.mnt_dir = cacheMountDir;
409     tmntent.mnt_type = "xx";
410     tmntent.mnt_opts = "rw";
411     tmntent.mnt_freq = 1;
412     tmntent.mnt_passno = 3;
413 #ifdef  AFS_HPUX_ENV
414     tmntent.mnt_type = "afs";
415     tmntent.mnt_time = time(0);
416     tmntent.mnt_cnode = 0;
417 #endif
418     addmntent(tfilep, &tmntent);
419     endmntent(tfilep);
420 #endif /* AFS_SGI_ENV */
421 #endif /* unreasonable systems */
422 #ifdef AFS_DARWIN_ENV
423 #ifndef AFS_DARWIN100_ENV
424     mach_port_t diskarb_port;
425     kern_return_t status;
426
427     status = DiskArbStart(&diskarb_port);
428     if (status == KERN_SUCCESS) {
429         status =
430             DiskArbDiskAppearedWithMountpointPing_auto("AFS",
431                                                        DISK_ARB_NETWORK_DISK_FLAG,
432                                                        cacheMountDir);
433     }
434
435     return status;
436 #endif
437 #endif /* AFS_DARWIN_ENV */
438     return 0;
439 }
440
441 void
442 afsd_mount_afs(const char *rn, const char *cacheMountDir)
443 {
444     int mountFlags;             /*Flags passed to mount() */
445     char *mountDir; /* For HandleMTab() */
446
447     mountFlags = 0;             /* Read/write file system, can do setuid() */
448 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
449 #ifdef  AFS_SUN5_ENV
450     mountFlags |= MS_DATA;
451 #else
452     mountFlags |= M_NEWTYPE;    /* This searches by name in vfs_conf.c so don't need to recompile vfs.c because MOUNT_MAXTYPE has changed; it seems that Sun fixed this at last... */
453 #endif
454 #endif
455
456 #if defined(AFS_HPUX100_ENV)
457     mountFlags |= MS_DATA;
458 #endif
459
460     if (afsd_verbose)
461         printf("%s: Mounting the AFS root on '%s', flags: %d.\n", rn,
462             cacheMountDir, mountFlags);
463 #if defined(AFS_FBSD60_ENV)
464     /* data must be non-NULL but is otherwise ignored */
465     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, rn)) < 0) {
466 #elif defined(AFS_FBSD_ENV)
467     if ((mount("AFS", cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
468 #elif defined(AFS_AIX_ENV)
469     if (aix_vmount(cacheMountDir)) {
470 #elif defined(AFS_HPUX100_ENV)
471     if ((mount("", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
472 #elif defined(AFS_SUN5_ENV)
473     if ((mount("AFS", cacheMountDir, mountFlags, "afs", NULL, 0)) < 0) {
474 #elif defined(AFS_SGI_ENV)
475     mountFlags = MS_FSS;
476     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) MOUNT_AFS))
477         < 0) {
478 #elif defined(AFS_LINUX20_ENV)
479     if ((mount("AFS", cacheMountDir, MOUNT_AFS, 0, NULL)) < 0) {
480 #elif defined(AFS_NBSD50_ENV)
481     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, NULL, 0)) < 0) {
482 #else
483     /* This is the standard mount used by the suns and rts */
484     if ((mount(MOUNT_AFS, cacheMountDir, mountFlags, (caddr_t) 0)) < 0) {
485 #endif
486         printf("%s: Can't mount AFS on %s(%d)\n", rn, cacheMountDir,
487                 errno);
488         exit(1);
489     }
490
491     mountDir = strdup(cacheMountDir);
492     HandleMTab(mountDir);
493     free(mountDir);
494 }
495
496 int
497 afsd_fork(int wait, afsd_callback_func cb, void *rock)
498 {
499     int code;
500     code = fork();
501     if (code == 0) {
502         (*cb) (rock);
503         exit(1);
504     } else {
505         assert(code > 0);
506         if (wait) {
507             assert(waitpid(code, NULL, 0) != -1);
508         }
509     }
510     return 0;
511 }
512
513 int
514 afsd_daemon(int nochdir, int noclose)
515 {
516     return daemon(nochdir, noclose);
517 }
518
519 int
520 afsd_check_mount(const char *rn, const char *mountdir)
521 {
522     struct stat statbuf;
523
524     if (stat(mountdir, &statbuf)) {
525         printf("%s: Mountpoint %s missing.\n", rn, mountdir);
526         return -1;
527     } else if (!S_ISDIR(statbuf.st_mode)) {
528         printf("%s: Mountpoint %s is not a directory.\n", rn, mountdir);
529         return -1;
530     }
531     return 0;
532 }
533
534 int
535 main(int argc, char **argv)
536 {
537     int code;
538
539     afsd_init();
540
541     code = afsd_parse(argc, argv);
542     if (code) {
543         return -1;
544     }
545
546     return afsd_run();
547 }