VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c@ 99425

Last change on this file since 99425 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.0 KB
Line 
1/* $Id: mount.vboxsf.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VirtualBox Guest Additions for Linux - mount(8) helper.
4 *
5 * Parses options provided by mount (or user directly)
6 * Packs them into struct vbsfmount and passes to mount(2)
7 * Optionally adds entries to mtab
8 */
9
10/*
11 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
12 *
13 * This file is part of VirtualBox base platform packages, as
14 * available from https://www.virtualbox.org.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation, in version 3 of the
19 * License.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses>.
28 *
29 * SPDX-License-Identifier: GPL-3.0-only
30 */
31
32
33#ifndef _GNU_SOURCE
34# define _GNU_SOURCE
35#endif
36
37/* #define DEBUG */
38#include <errno.h>
39#include <fcntl.h>
40#include <ctype.h>
41#include <getopt.h>
42#include <mntent.h>
43#include <pwd.h>
44#include <stdarg.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <stdint.h>
48#include <string.h>
49#include <sys/mount.h>
50#include <sys/stat.h>
51#include <sys/types.h>
52#include <unistd.h>
53#include <mntent.h>
54#include <limits.h>
55#include <iconv.h>
56#include <sys/utsname.h>
57#include <linux/version.h>
58
59#include "vbsfmount.h"
60
61#include <iprt/assertcompile.h>
62#include <iprt/param.h> /* PAGE_SIZE (used by MAX_MNTOPT_STR) */
63#include <iprt/string.h>
64
65
66/*********************************************************************************************************************************
67* Defined Constants And Macros *
68*********************************************************************************************************************************/
69#define PANIC_ATTR __attribute ((noreturn, __format__ (__printf__, 1, 2)))
70
71
72/*********************************************************************************************************************************
73* Structures and Typedefs *
74*********************************************************************************************************************************/
75struct vbsf_mount_opts
76{
77 unsigned long fFlags; /**< MS_XXX */
78
79 /** @name Preformatted option=value or empty if not specified.
80 * Helps eliminate duplicate options as well as simplifying concatting.
81 * @{ */
82 char szTTL[32];
83 char szMsDirCacheTTL[32];
84 char szMsInodeTTL[32];
85 char szMaxIoPages[32];
86 char szDirBuf[32];
87 char szCacheMode[32];
88 char szUid[32];
89 char szGid[32];
90 char szDMode[32];
91 char szFMode[32];
92 char szDMask[32];
93 char szFMask[32];
94 char szIoCharset[32];
95 /** @} */
96
97 bool fSloppy;
98 char *pszConvertCp;
99};
100
101
102static void PANIC_ATTR
103panic(const char *fmt, ...)
104{
105 va_list ap;
106
107 va_start(ap, fmt);
108 vfprintf(stderr, fmt, ap);
109 va_end(ap);
110 exit(EXIT_FAILURE);
111}
112
113static void PANIC_ATTR
114panic_err(const char *fmt, ...)
115{
116 va_list ap;
117 int errno_code = errno;
118
119 va_start(ap, fmt);
120 vfprintf(stderr, fmt, ap);
121 va_end(ap);
122 fprintf(stderr, ": %s\n", strerror(errno_code));
123 exit(EXIT_FAILURE);
124}
125
126static int
127safe_atoi(const char *s, size_t size, int base)
128{
129 char *endptr;
130 long long int val = strtoll(s, &endptr, base);
131
132 if ( val < INT_MIN
133 || ( val > INT_MAX
134 && (base != 8 || val != UINT_MAX) ) /* hack for printf("%o", -1) - 037777777777 */
135 || endptr < s + size)
136 {
137 errno = ERANGE;
138 panic_err("could not convert %.*s to integer, result = %lld (%d)",
139 (int)size, s, val, (int)val);
140 }
141 return (int)val;
142}
143
144static unsigned
145safe_atoiu(const char *s, size_t size, int base)
146{
147 char *endptr;
148 long long int val = strtoll(s, &endptr, base);
149
150 if ( val < 0
151 || val > UINT_MAX
152 || endptr < s + size)
153 {
154 errno = ERANGE;
155 panic_err("could not convert %.*s to unsigned integer, result = %lld (%#llx)",
156 (int)size, s, val, val);
157 }
158 return (unsigned)val;
159}
160
161static void
162process_mount_opts(const char *s, struct vbsf_mount_opts *opts)
163{
164 const char *next = s;
165 size_t len;
166 typedef enum handler_opt
167 {
168 HO_RW,
169 HO_RO,
170 HO_UID,
171 HO_GID,
172 HO_TTL,
173 HO_DENTRY_TTL,
174 HO_INODE_TTL,
175 HO_MAX_IO_PAGES,
176 HO_DIR_BUF,
177 HO_CACHE,
178 HO_DMODE,
179 HO_FMODE,
180 HO_UMASK,
181 HO_DMASK,
182 HO_FMASK,
183 HO_IOCHARSET,
184 HO_NLS,
185 HO_CONVERTCP,
186 HO_NOEXEC,
187 HO_EXEC,
188 HO_NODEV,
189 HO_DEV,
190 HO_NOSUID,
191 HO_SUID,
192 HO_REMOUNT,
193 HO_NOAUTO,
194 HO_NIGNORE
195 } handler_opt;
196 struct
197 {
198 const char *name;
199 handler_opt opt;
200 int has_arg;
201 const char *desc;
202 } handlers[] =
203 {
204 {"rw", HO_RW, 0, "mount read write (default)"},
205 {"ro", HO_RO, 0, "mount read only"},
206 {"uid", HO_UID, 1, "default file owner user id"},
207 {"gid", HO_GID, 1, "default file owner group id"},
208 {"ttl", HO_TTL, 1, "time to live for dentries & inode info"},
209 {"dcachettl", HO_DENTRY_TTL, 1, "time to live for dentries"},
210 {"inodettl", HO_INODE_TTL, 1, "time to live for inode info"},
211 {"maxiopages", HO_MAX_IO_PAGES, 1, "max buffer size for I/O with host"},
212 {"dirbuf", HO_DIR_BUF, 1, "directory buffer size (0 for default)"},
213 {"cache", HO_CACHE, 1, "cache mode: none, strict (default), read, readwrite"},
214 {"iocharset", HO_IOCHARSET, 1, "i/o charset (default utf8)"},
215 {"nls", HO_NLS, 1, "i/o charset (default utf8)"},
216 {"convertcp", HO_CONVERTCP, 1, "convert share name from given charset to utf8"},
217 {"dmode", HO_DMODE, 1, "mode of all directories"},
218 {"fmode", HO_FMODE, 1, "mode of all regular files"},
219 {"umask", HO_UMASK, 1, "umask of directories and regular files"},
220 {"dmask", HO_DMASK, 1, "umask of directories"},
221 {"fmask", HO_FMASK, 1, "umask of regular files"},
222 {"noexec", HO_NOEXEC, 0, NULL}, /* don't document these options directly here */
223 {"exec", HO_EXEC, 0, NULL}, /* as they are well known and described in the */
224 {"nodev", HO_NODEV, 0, NULL}, /* usual manpages */
225 {"dev", HO_DEV, 0, NULL},
226 {"nosuid", HO_NOSUID, 0, NULL},
227 {"suid", HO_SUID, 0, NULL},
228 {"remount", HO_REMOUNT, 0, NULL},
229 {"noauto", HO_NOAUTO, 0, NULL},
230 {"_netdev", HO_NIGNORE, 0, NULL},
231 {"relatime", HO_NIGNORE, 0, NULL},
232 {NULL, 0, 0, NULL}
233 }, *handler;
234
235 while (next)
236 {
237 const char *val;
238 size_t key_len, val_len;
239
240 s = next;
241 next = strchr(s, ',');
242 if (!next)
243 {
244 len = strlen(s);
245 }
246 else
247 {
248 len = next - s;
249 next += 1;
250 if (!*next)
251 next = 0;
252 }
253
254 val = NULL;
255 val_len = 0;
256 for (key_len = 0; key_len < len; ++key_len)
257 {
258 if (s[key_len] == '=')
259 {
260 if (key_len + 1 < len)
261 {
262 val = s + key_len + 1;
263 val_len = len - key_len - 1;
264 }
265 break;
266 }
267 }
268
269 for (handler = handlers; handler->name; ++handler)
270 {
271 size_t j;
272 for (j = 0; j < key_len && handler->name[j] == s[j]; ++j)
273 ;
274
275 if (j == key_len && !handler->name[j])
276 {
277 if (handler->has_arg)
278 {
279 if (!(val && *val))
280 {
281 panic("%.*s requires an argument (i.e. %.*s=<arg>)\n",
282 (int)len, s, (int)len, s);
283 }
284 }
285
286 switch (handler->opt)
287 {
288 case HO_RW:
289 opts->fFlags &= ~MS_RDONLY;
290 break;
291 case HO_RO:
292 opts->fFlags |= MS_RDONLY;
293 break;
294 case HO_NOEXEC:
295 opts->fFlags |= MS_NOEXEC;
296 break;
297 case HO_EXEC:
298 opts->fFlags &= ~MS_NOEXEC;
299 break;
300 case HO_NODEV:
301 opts->fFlags |= MS_NODEV;
302 break;
303 case HO_DEV:
304 opts->fFlags &= ~MS_NODEV;
305 break;
306 case HO_NOSUID:
307 opts->fFlags |= MS_NOSUID;
308 break;
309 case HO_SUID:
310 opts->fFlags &= ~MS_NOSUID;
311 break;
312 case HO_REMOUNT:
313 opts->fFlags |= MS_REMOUNT;
314 break;
315 case HO_TTL:
316 snprintf(opts->szTTL, sizeof(opts->szTTL),
317 "ttl=%d", safe_atoi(val, val_len, 10));
318 break;
319 case HO_DENTRY_TTL:
320 snprintf(opts->szMsDirCacheTTL, sizeof(opts->szMsDirCacheTTL),
321 "dcachettl=%d", safe_atoi(val, val_len, 10));
322 break;
323 case HO_INODE_TTL:
324 snprintf(opts->szMsInodeTTL, sizeof(opts->szMsInodeTTL),
325 "inodettl=%d", safe_atoi(val, val_len, 10));
326 break;
327 case HO_MAX_IO_PAGES:
328 snprintf(opts->szMaxIoPages, sizeof(opts->szMaxIoPages),
329 "maxiopages=%d", safe_atoiu(val, val_len, 10));
330 break;
331 case HO_DIR_BUF:
332 snprintf(opts->szDirBuf, sizeof(opts->szDirBuf),
333 "dirbuf=%d", safe_atoiu(val, val_len, 10));
334 break;
335 case HO_CACHE:
336#define IS_EQUAL(a_sz) (val_len == sizeof(a_sz) - 1U && strncmp(val, a_sz, sizeof(a_sz) - 1U) == 0)
337 if (IS_EQUAL("default"))
338 strcpy(opts->szCacheMode, "cache=default");
339 else if (IS_EQUAL("none"))
340 strcpy(opts->szCacheMode, "cache=none");
341 else if (IS_EQUAL("strict"))
342 strcpy(opts->szCacheMode, "cache=strict");
343 else if (IS_EQUAL("read"))
344 strcpy(opts->szCacheMode, "cache=read");
345 else if (IS_EQUAL("readwrite"))
346 strcpy(opts->szCacheMode, "cache=readwrite");
347 else
348 panic("invalid cache mode '%.*s'\n"
349 "Valid cache modes are: default, none, strict, read, readwrite\n",
350 (int)val_len, val);
351 break;
352 case HO_UID:
353 /** @todo convert string to id. */
354 snprintf(opts->szUid, sizeof(opts->szUid),
355 "uid=%d", safe_atoi(val, val_len, 10));
356 break;
357 case HO_GID:
358 /** @todo convert string to id. */
359 snprintf(opts->szGid, sizeof(opts->szGid),
360 "gid=%d", safe_atoi(val, val_len, 10));
361 break;
362 case HO_DMODE:
363 snprintf(opts->szDMode, sizeof(opts->szDMode),
364 "dmode=0%o", safe_atoi(val, val_len, 8));
365 break;
366 case HO_FMODE:
367 snprintf(opts->szFMode, sizeof(opts->szFMode),
368 "fmode=0%o", safe_atoi(val, val_len, 8));
369 break;
370 case HO_UMASK:
371 {
372 int fMask = safe_atoi(val, val_len, 8);
373 snprintf(opts->szDMask, sizeof(opts->szDMask), "dmask=0%o", fMask);
374 snprintf(opts->szFMask, sizeof(opts->szFMask), "fmask=0%o", fMask);
375 break;
376 }
377 case HO_DMASK:
378 snprintf(opts->szDMask, sizeof(opts->szDMask),
379 "dmask=0%o", safe_atoi(val, val_len, 8));
380 break;
381 case HO_FMASK:
382 snprintf(opts->szFMask, sizeof(opts->szFMask),
383 "fmask=0%o", safe_atoi(val, val_len, 8));
384 break;
385 case HO_IOCHARSET:
386 case HO_NLS:
387 if (val_len >= MAX_NLS_NAME)
388 panic("the character set name for I/O is too long: %*.*s\n", (int)val_len, (int)val_len, val);
389 snprintf(opts->szIoCharset, sizeof(opts->szIoCharset),
390 "%s=%*.*s", handler->opt == HO_IOCHARSET ? "iocharset" : "nls", (int)val_len, (int)val_len, val);
391 break;
392 case HO_CONVERTCP:
393 opts->pszConvertCp = malloc(val_len + 1);
394 if (!opts->pszConvertCp)
395 panic_err("could not allocate memory");
396 memcpy(opts->pszConvertCp, val, val_len);
397 opts->pszConvertCp[val_len] = '\0';
398 break;
399 case HO_NOAUTO:
400 case HO_NIGNORE:
401 break;
402 }
403 break;
404 }
405 continue;
406 }
407
408 if ( !handler->name
409 && !opts->fSloppy)
410 {
411 fprintf(stderr, "unknown mount option `%.*s'\n", (int)len, s);
412 fprintf(stderr, "valid options:\n");
413
414 for (handler = handlers; handler->name; ++handler)
415 {
416 if (handler->desc)
417 fprintf(stderr, " %-10s%s %s\n", handler->name,
418 handler->has_arg ? "=<arg>" : "", handler->desc);
419 }
420 exit(EXIT_FAILURE);
421 }
422 }
423}
424
425/** Appends @a pszOptVal to pszOpts if not empty. */
426static size_t append_option(char *pszOpts, size_t cbOpts, size_t offOpts, const char *pszOptVal)
427{
428 if (*pszOptVal != '\0')
429 {
430 size_t cchOptVal = strlen(pszOptVal);
431 if (offOpts + (offOpts > 0) + cchOptVal < cbOpts)
432 {
433 if (offOpts)
434 pszOpts[offOpts++] = ',';
435 memcpy(&pszOpts[offOpts], pszOptVal, cchOptVal);
436 offOpts += cchOptVal;
437 pszOpts[offOpts] = '\0';
438 }
439 else
440 panic("Too many options!");
441 }
442 return offOpts;
443}
444
445static void
446convertcp(char *in_codeset, char *pszSharedFolder, char *pszDst)
447{
448 char *i = pszSharedFolder;
449 char *o = pszDst;
450 size_t ib = strlen(pszSharedFolder);
451 size_t ob = MAX_HOST_NAME - 1;
452 iconv_t cd;
453
454 cd = iconv_open("UTF-8", in_codeset);
455 if (cd == (iconv_t)-1)
456 {
457 panic_err("could not convert share name, iconv_open `%s' failed",
458 in_codeset);
459 }
460
461 while (ib)
462 {
463 size_t c = iconv(cd, &i, &ib, &o, &ob);
464 if (c == (size_t)-1)
465 {
466 panic_err("could not convert share name(%s) at %d",
467 pszSharedFolder, (int)(strlen(pszSharedFolder) - ib));
468 }
469 }
470 *o = 0;
471}
472
473
474/**
475 * Print out a usage message and exit.
476 *
477 * @returns 1
478 * @param argv0 The name of the application
479 */
480static int usage(char *argv0)
481{
482 printf("Usage: %s [OPTIONS] NAME MOUNTPOINT\n"
483 "Mount the VirtualBox shared folder NAME from the host system to MOUNTPOINT.\n"
484 "\n"
485 " -w mount the shared folder writable (the default)\n"
486 " -r mount the shared folder read-only\n"
487 " -n do not create an mtab entry\n"
488 " -s sloppy parsing, ignore unrecognized mount options\n"
489 " -o OPTION[,OPTION...] use the mount options specified\n"
490 "\n", argv0);
491 printf("Available mount options are:\n"
492 " rw mount writable (the default)\n"
493 " ro mount read only\n"
494 " uid=UID set the default file owner user id to UID\n"
495 " gid=GID set the default file owner group id to GID\n");
496 printf(" ttl=MILLIESECSONDS set the \"time to live\" for both the directory cache\n"
497 " and inode info. -1 for kernel default, 0 disables it.\n"
498 " dcachettl=MILLIES set the \"time to live\" for the directory cache,\n"
499 " overriding the 'ttl' option. Ignored if negative.\n"
500 " inodettl=MILLIES set the \"time to live\" for the inode information,\n"
501 " overriding the 'ttl' option. Ignored if negative.\n");
502 printf(" maxiopages=PAGES set the max host I/O buffers size in pages. Uses\n"
503 " default if zero.\n"
504 " dirbuf=BYTES set the directory enumeration buffer size in bytes.\n"
505 " Uses default size if zero.\n");
506 printf(" cache=MODE set the caching mode for the mount. Allowed values:\n"
507 " default: use the kernel default (strict)\n"
508 " none: no caching; may experience guest side\n"
509 " coherence issues between mmap and read.\n");
510 printf(" strict: no caching, except for writably mapped\n"
511 " files (for guest side coherence)\n"
512 " read: read via the page cache; host changes\n"
513 " may be completely ignored\n");
514 printf(" readwrite: read and write via the page cache; host\n"
515 " changes may be completely ignored and\n"
516 " guest changes takes a while to reach the host\n");
517 printf(" dmode=MODE override the mode of all directories to (octal) MODE\n"
518 " fmode=MODE override the mode of all regular files to (octal) MODE\n"
519 " umask=UMASK set the umask to (octal) UMASK\n");
520 printf(" dmask=UMASK set the umask applied to directories only\n"
521 " fmask=UMASK set the umask applied to regular files only\n"
522 " iocharset CHARSET use the character set CHARSET for I/O operations\n"
523 " (default set is utf8)\n"
524 " convertcp CHARSET convert the folder name from CHARSET to utf8\n"
525 "\n");
526 printf("Less common used options:\n"
527 " noexec,exec,nodev,dev,nosuid,suid\n");
528 return EXIT_FAILURE;
529}
530
531int
532main(int argc, char **argv)
533{
534 int c;
535 int err;
536 int saved_errno;
537 int nomtab = 0;
538 char *pszSharedFolder;
539 char *pszMountPoint;
540 struct utsname uts;
541 int major, minor, patch;
542 size_t offOpts;
543 static const char s_szSfNameOpt[] = "sf_name=";
544 char szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1 + MAX_HOST_NAME];
545 char szOpts[MAX_MNTOPT_STR];
546 struct vbsf_mount_opts opts =
547 {
548 MS_NODEV,
549 "",
550 "",
551 "",
552 "",
553 "",
554 "",
555 "",
556 "",
557 "",
558 "",
559 "",
560 "",
561 "",
562 false, /*fSloppy*/
563 NULL,
564 };
565
566 AssertCompile(sizeof(uid_t) == sizeof(int));
567 AssertCompile(sizeof(gid_t) == sizeof(int));
568
569 if (getuid())
570 panic("Only root can mount shared folders from the host.\n");
571
572 if (!argv[0])
573 argv[0] = "mount.vboxsf";
574
575 /*
576 * Parse options.
577 */
578 while ((c = getopt(argc, argv, "rwsno:h")) != -1)
579 {
580 switch (c)
581 {
582 default:
583 fprintf(stderr, "unknown option `%c:%#x'\n", c, c);
584 RT_FALL_THRU();
585 case '?':
586 case 'h':
587 return usage(argv[0]);
588
589 case 'r':
590 opts.fFlags |= MS_RDONLY;
591 break;
592
593 case 'w':
594 opts.fFlags &= ~MS_RDONLY;
595 break;
596
597 case 's':
598 opts.fSloppy = true;
599 break;
600
601 case 'o':
602 process_mount_opts(optarg, &opts);
603 break;
604
605 case 'n':
606 nomtab = 1;
607 break;
608 }
609 }
610
611 if (argc - optind < 2)
612 return usage(argv[0]);
613
614 pszSharedFolder = argv[optind];
615 pszMountPoint = argv[optind + 1];
616 if (opts.pszConvertCp)
617 {
618 convertcp(opts.pszConvertCp, pszSharedFolder, &szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1]);
619 pszSharedFolder = &szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1];
620 }
621
622 /*
623 * Concat option strings.
624 */
625 offOpts = 0;
626 szOpts[0] = '\0';
627 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szTTL);
628 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMsDirCacheTTL);
629 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMsInodeTTL);
630 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMaxIoPages);
631 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDirBuf);
632 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szCacheMode);
633 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szUid);
634 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szGid);
635 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDMode);
636 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szFMode);
637 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDMask);
638 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szFMask);
639 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szIoCharset);
640
641 /* For pre-2.6 kernels we have to supply the shared folder name as a
642 string option because the kernel hides the device name from us. */
643 RT_ZERO(uts);
644 if ( uname(&uts) == -1
645 || sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3)
646 major = minor = patch = 5;
647
648 if (KERNEL_VERSION(major, minor, patch) < KERNEL_VERSION(2,6,0))
649 {
650 memcpy(szSharedFolderIconved, s_szSfNameOpt, sizeof(s_szSfNameOpt) - 1);
651 if (!opts.pszConvertCp)
652 {
653 if (strlen(pszSharedFolder) >= MAX_HOST_NAME)
654 panic("%s: shared folder name is too long (max %d)", argv[0], (int)MAX_HOST_NAME - 1);
655 strcpy(&szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1], pszSharedFolder);
656 }
657 offOpts = append_option(szOpts, sizeof(szOpts), offOpts, szSharedFolderIconved);
658 }
659
660 /*
661 * Do the actual mounting.
662 */
663 err = mount(pszSharedFolder, pszMountPoint, "vboxsf", opts.fFlags, szOpts);
664 saved_errno = errno;
665
666 if (err)
667 {
668 if (saved_errno == ENXIO)
669 panic("%s: shared folder '%s' was not found (check VM settings / spelling)\n", argv[0], pszSharedFolder);
670 else
671 panic_err("%s: mounting failed with the error", argv[0]);
672 }
673
674 if (!nomtab)
675 {
676 err = vbsfmount_complete(pszSharedFolder, pszMountPoint, opts.fFlags, szOpts);
677 switch (err)
678 {
679 case 0: /* Success. */
680 break;
681
682 case 1:
683 panic_err("%s: Could not update mount table (out of memory).", argv[0]);
684 break;
685
686 case 2:
687 panic_err("%s: Could not open mount table for update.", argv[0]);
688 break;
689
690 case 3:
691 /* panic_err("%s: Could not add an entry to the mount table.", argv[0]); */
692 break;
693
694 default:
695 panic_err("%s: Unknown error while completing mount operation: %d", argv[0], err);
696 break;
697 }
698 }
699
700 exit(EXIT_SUCCESS);
701}
702
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette