4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
21 #pragma ident "%Z%%M% %I% %E% SMI"
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <sys/types.h>
37 #include <sys/mntent.h>
38 #include <sys/mnttab.h>
39 #include <sys/mount.h>
40 #include <sys/fs/pc_fs.h>
45 static int roflag
= 0;
46 static char optbuf
[MAX_MNTOPT_STR
] = { '\0', };
47 static int optsize
= 0;
51 * Since the format/value expected for the mount options listed below
52 * differs between what the user mount command expects and what the
53 * kernel module can grok, we transmogrify the mount option string
54 * for such options. Others are copied through as-is.
56 static char *pcfs_opts
[] = { MNTOPT_PCFS_TIMEZONE
, NULL
};
57 #define ARG_PCFS_TIMEZONE 0
60 * While constructing the mount option string, we need to append
61 * comma separators if there have been previous options copied over
62 * from the input string. This takes care of it.
65 append_opt(char *str
, int strsz
, char *opt
)
67 if (str
[0] != '\0' && strlcat(str
, ",", strsz
) >= strsz
)
70 return (strlcat(str
, opt
, strsz
) < strsz
);
74 main(int argc
, char *argv
[])
83 char *savedoptbuf
= NULL
, *savedoptarg
= NULL
;
84 char *in_arg
, *val
, *curarg
;
89 int mflg
= MS_OPTIONSTR
; /* we always pass mount options */
94 myname
= strrchr(argv
[0], '/');
95 myname
= myname
? myname
+ 1 : argv
[0];
96 (void) snprintf(typename
, sizeof (typename
), "%s_%s",
97 MNTTYPE_PCFS
, myname
);
100 while ((c
= getopt(argc
, argv
, "Vvmr?o:Oq")) != EOF
) {
117 if ((savedoptarg
= strdup(optarg
)) == NULL
) {
118 (void) fprintf(stderr
,
119 gettext("%s: out of memory\n"), myname
);
122 while (*in_arg
!= '\0') {
125 switch (getsubopt(&in_arg
, pcfs_opts
, &val
)) {
126 case ARG_PCFS_TIMEZONE
:
127 if (tzdone
|| val
== NULL
)
130 (void) snprintf(tzstr
, 100,
133 (void) putenv(tzstr
);
138 * Remove empty suboptions
139 * (happens on sequences of commas)
144 if (append_opt(optbuf
, sizeof (optbuf
),
159 if (verbose
&& !error
) {
162 (void) fprintf(stderr
, "%s", typename
);
163 for (optcnt
= 1; optcnt
< argc
; optcnt
++) {
164 optptr
= argv
[optcnt
];
166 (void) fprintf(stderr
, " %s", optptr
);
168 (void) fprintf(stderr
, "\n");
171 if (argc
- optind
!= 2 || error
) {
173 * don't hint at options yet (none are really supported)
175 (void) fprintf(stderr
, gettext(
176 "Usage: %s [generic options] [-o suboptions] "
177 "special mount_point\n"), typename
);
178 (void) fprintf(stderr
, gettext(
179 "\tpcfs-specific suboptions are:\n"
180 "\t clamptime,noclamptime\n"
181 "\t hidden,nohidden\n"
183 "\t foldcase,nofoldcase\n"
184 "\t timezone=<valid TZ string>"));
188 mnt_special
= argv
[optind
++];
189 mnt_mountp
= argv
[optind
++];
192 * Pass timezone information to the kernel module so that
193 * FAT timestamps, as per spec, can be recorded in local time.
197 * We perform this validation only in case the user of
198 * mount(1m) specified the "timezone=..." option. That's
199 * because we don't want PCFS mounts to fail due to a
200 * botched $TZ environment variable. If the admin's
201 * environment contains garbage, it'll just parse as
204 if (tzdone
&& timezone
== 0 && altzone
== 0 && daylight
== 0 &&
205 strcmp(tzname
[0], tzval
) &&
206 strspn(tzname
[1], " ") == strlen(tzname
[1])) {
209 (void) snprintf(tzstr
, 100, "timezone=%d", timezone
);
211 if (append_opt(optbuf
, sizeof (optbuf
), tzstr
) == 0)
214 optsize
= strlen(optbuf
);
219 if ((savedoptbuf
= strdup(optbuf
)) == NULL
) {
220 (void) fprintf(stderr
, gettext("%s: out of memory\n"),
224 (void) signal(SIGHUP
, SIG_IGN
);
225 (void) signal(SIGQUIT
, SIG_IGN
);
226 (void) signal(SIGINT
, SIG_IGN
);
229 (void) fprintf(stderr
, "mount(%s, \"%s\", %d, %s",
230 mnt_special
, mnt_mountp
, mflg
, MNTTYPE_PCFS
);
232 if (mount(mnt_special
, mnt_mountp
, mflg
, MNTTYPE_PCFS
,
233 NULL
, 0, optbuf
, MAX_MNTOPT_STR
)) {
234 if (errno
== EBUSY
) {
235 (void) fprintf(stderr
, gettext(
236 "mount: %s is already mounted or %s is busy\n"),
237 mnt_special
, mnt_mountp
);
238 } else if (errno
== EINVAL
) {
239 (void) fprintf(stderr
, gettext(
240 "mount: %s is not a DOS filesystem.\n"),
248 if (optsize
&& !qflg
)
249 cmp_requested_to_actual_options(savedoptbuf
, optbuf
,
250 mnt_special
, mnt_mountp
);
254 (void) fprintf(stderr
,
255 gettext("%s: Invalid mount options: %s\n"), myname
, savedoptarg
);