VirtualBox

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

Last change on this file was 100317, checked in by vboxsync, 10 months ago

Additions: Get rid of MAX_MNTOPT_STR and replace with RTSystemGetPageSize() in the shared folders mounting tools, bugref:10476

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

© 2023 Oracle
ContactPrivacy policyTerms of Use