xref: /illumos-gate/usr/src/cmd/cdrw/bstream.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <fcntl.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <sys/statvfs.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <libintl.h>
38 #include <limits.h>
39 #include <audio/au.h>
40 
41 #include "bstream.h"
42 #include "util.h"
43 #include "audio.h"
44 #include "byteorder.h"
45 #include "main.h"
46 
47 int str_errno;
48 
49 char *
50 str_errno_to_string(int serrno)
51 {
52 	switch (serrno) {
53 	case STR_ERR_NO_ERR:
54 		return (gettext("No error"));
55 	case STR_ERR_NO_REG_FILE:
56 		return (gettext("Not a regular file"));
57 	case STR_ERR_NO_READ_STDIN:
58 		return (gettext("Stdin not open for reading"));
59 	case STR_ERR_AU_READ_ERR:
60 		return (gettext("Unable to read au header"));
61 	case STR_ERR_AU_UNSUPPORTED_FORMAT:
62 		return (gettext("Unsupported au format"));
63 	case STR_ERR_AU_BAD_HEADER:
64 		return (gettext("Bad au header"));
65 	case STR_ERR_WAV_READ_ERR:
66 		return (gettext("Unable to read wav header"));
67 	case STR_ERR_WAV_UNSUPPORTED_FORMAT:
68 		return (gettext("Unsupported wav format"));
69 	case STR_ERR_WAV_BAD_HEADER:
70 		return (gettext("Bad wav header"));
71 	case STR_ERR_ISO_READ_ERR:
72 		return (gettext("Unable to read ISO header"));
73 	case STR_ERR_ISO_BAD_HEADER:
74 		return (gettext("Invalid ISO header or not an ISO"));
75 	default:
76 		return (gettext("unknown error"));
77 	}
78 }
79 
80 static int
81 file_stream_size(bstreamhandle h, off_t *size)
82 {
83 	struct stat st;
84 
85 	str_errno = 0;
86 
87 	if (fstat(h->bstr_fd, &st) < 0)
88 		return (0);
89 	if ((st.st_mode & S_IFMT) != S_IFREG) {
90 		str_errno = STR_ERR_NO_REG_FILE;
91 		return (0);
92 	}
93 	*size = st.st_size;
94 	return (1);
95 }
96 
97 static int
98 audio_stream_size(bstreamhandle h, off_t *size)
99 {
100 	str_errno = 0;
101 	*size = (off_t)(uintptr_t)(h->bstr_private);
102 	return (1);
103 }
104 
105 static int
106 file_stream_read(bstreamhandle h, uchar_t *buf, off_t size)
107 {
108 	str_errno = 0;
109 	return (read(h->bstr_fd, buf, size));
110 }
111 
112 static int
113 file_stream_write(bstreamhandle h, uchar_t *buf, off_t size)
114 {
115 	str_errno = 0;
116 	return (write(h->bstr_fd, buf, size));
117 }
118 
119 /*
120  * with reverse byteorder
121  */
122 static int
123 file_stream_read_wrbo(bstreamhandle h, uchar_t *buf, off_t size)
124 {
125 	int cnt;
126 
127 	str_errno = 0;
128 	cnt = read(h->bstr_fd, buf, size);
129 	if (cnt > 0) {
130 		int i;
131 		uchar_t ch;
132 
133 		for (i = 0; i < cnt; i += 2) {
134 			ch = buf[i];
135 			buf[i] = buf[i+1];
136 			buf[i+1] = ch;
137 		}
138 	}
139 	return (cnt);
140 }
141 
142 /*
143  * This will change the byteorder in the buffer but that is fine with us.
144  */
145 static int
146 file_stream_write_wrbo(bstreamhandle h, uchar_t *buf, off_t size)
147 {
148 	int i;
149 	uchar_t ch;
150 
151 	str_errno = 0;
152 	if (size > 0) {
153 		for (i = 0; i < size; i += 2) {
154 			ch = buf[i];
155 			buf[i] = buf[i+1];
156 			buf[i+1] = ch;
157 		}
158 	}
159 	return (write(h->bstr_fd, buf, size));
160 }
161 
162 static int
163 file_stream_close(bstreamhandle h)
164 {
165 	int fd;
166 
167 	str_errno = 0;
168 	fd = h->bstr_fd;
169 	free(h);
170 	return (close(fd));
171 }
172 
173 static int
174 stdin_stream_close(bstreamhandle h)
175 {
176 	str_errno = 0;
177 	free(h);
178 	return (0);
179 }
180 
181 static int
182 wav_write_stream_close(bstreamhandle h)
183 {
184 	uint32_t sz;
185 	Wave_filehdr wav;
186 
187 	str_errno = 0;
188 	(void) memset(&wav, 0, sizeof (wav));
189 	sz = lseek(h->bstr_fd, 0L, SEEK_END);
190 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
191 	if (read(h->bstr_fd, &wav, sizeof (wav)) != sizeof (wav)) {
192 		return (1);
193 	}
194 	wav.total_chunk_size = CPU_TO_LE32(sz - 8);
195 	wav.data_size = CPU_TO_LE32(sz - 44);
196 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
197 	if (write(h->bstr_fd, &wav, sizeof (wav)) != sizeof (wav)) {
198 		return (1);
199 	}
200 	(void) close(h->bstr_fd);
201 	free(h);
202 	return (0);
203 }
204 
205 static int
206 au_write_stream_close(bstreamhandle h)
207 {
208 	uint32_t sz;
209 
210 	str_errno = 0;
211 	sz = lseek(h->bstr_fd, 0L, SEEK_END);
212 	sz -= PRE_DEF_AU_HDR_LEN;
213 	sz = CPU_TO_BE32(sz);
214 	if (lseek(h->bstr_fd, 8L, SEEK_SET) < 0)
215 		return (1);
216 
217 	if (write(h->bstr_fd, &sz, 4) < 0)
218 		return (1);
219 
220 	(void) close(h->bstr_fd);
221 	free(h);
222 	return (0);
223 }
224 
225 /* ARGSUSED */
226 static void
227 stdin_stream_rewind(bstreamhandle h)
228 {
229 }
230 
231 static void
232 file_stream_rewind(bstreamhandle h)
233 {
234 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
235 }
236 
237 static void
238 au_stream_rewind(bstreamhandle h)
239 {
240 	au_filehdr_t au;
241 
242 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
243 	if (read(h->bstr_fd, &au, sizeof (au)) != sizeof (au)) {
244 		return;
245 	}
246 
247 	if (lseek(h->bstr_fd, (long)(BE32_TO_CPU(au.au_offset)),
248 	    SEEK_SET) < 0) {
249 		return;
250 	}
251 }
252 
253 static void
254 wav_stream_rewind(bstreamhandle h)
255 {
256 	(void) lseek(h->bstr_fd, (long)(sizeof (Wave_filehdr)), SEEK_SET);
257 }
258 
259 bstreamhandle
260 open_file_read_stream(char *file)
261 {
262 	bstreamhandle h;
263 	int fd;
264 	struct stat st;
265 
266 	str_errno = 0;
267 	if (stat(file, &st) < 0)
268 		return (NULL);
269 	if ((st.st_mode & S_IFMT) == S_IFDIR) {
270 		str_errno = STR_ERR_NO_REG_FILE;
271 		return (NULL);
272 	}
273 	fd = open(file, O_RDONLY);
274 	if (fd < 0)
275 		return (NULL);
276 	h = (bstreamhandle)my_zalloc(sizeof (*h));
277 	h->bstr_fd = fd;
278 	h->bstr_read = file_stream_read;
279 	h->bstr_close = file_stream_close;
280 	h->bstr_size = file_stream_size;
281 	h->bstr_rewind = file_stream_rewind;
282 
283 	return (h);
284 }
285 
286 bstreamhandle
287 open_iso_read_stream(char *fname)
288 {
289 	bstreamhandle h;
290 	off_t iso_size = 0;
291 	char iso_desc[ISO9660_PRIMARY_DESC_SIZE];
292 
293 	h = open_file_read_stream(fname);
294 
295 	/* If we don't have a valid handle immediately return NULL */
296 	if (h == NULL)
297 		return (NULL);
298 
299 	if (debug)
300 		(void) printf("Checking the ISO 9660 file header\n");
301 
302 	/* Check to see if we have a valid sized ISO image */
303 	h->bstr_size(h, &iso_size);
304 	if (iso_size < ISO9660_HEADER_SIZE) {
305 		if (debug)
306 			(void) printf("ISO 9660 header size not sane.\n");
307 		h->bstr_close(h);
308 		str_errno = STR_ERR_ISO_BAD_HEADER;
309 		return (NULL);
310 	}
311 
312 	if (debug)
313 		(void) printf("ISO 9660 header size is sane.\n");
314 
315 	/* Skip over the boot block sector of the ISO. */
316 	(void) lseek(h->bstr_fd, ISO9660_BOOT_BLOCK_SIZE, SEEK_SET);
317 
318 	/*
319 	 * Try to read in the ISO Descriptor and validate this
320 	 * is in fact an ISO 9660 image.
321 	 */
322 	if (read(h->bstr_fd, iso_desc, ISO9660_PRIMARY_DESC_SIZE) ==
323 	    ISO9660_PRIMARY_DESC_SIZE) {
324 		/*
325 		 * Bytes one through five of a valid ISO 9660 cd image
326 		 * should contain the string CD001. High Sierra format,
327 		 * the ISO 9660 predecessor, fills this field with the
328 		 * string CDROM. If neither is the case then we should
329 		 * close the stream, set str_errno, and return NULL.
330 		 */
331 		if (strncmp(iso_desc + ISO9660_STD_IDENT_OFFSET, "CD001",
332 		    5) != 0 && strncmp(iso_desc + ISO9660_STD_IDENT_OFFSET,
333 		    "CDROM", 5) != 0) {
334 			if (debug)
335 				(void) printf("Invalid ISO 9660 identifier.\n");
336 			h->bstr_close(h);
337 			str_errno = STR_ERR_ISO_BAD_HEADER;
338 			return (NULL);
339 		}
340 	} else {
341 		h->bstr_close(h);
342 		str_errno = STR_ERR_ISO_READ_ERR;
343 		return (NULL);
344 	}
345 
346 	/*
347 	 * Our ISO image is valid rewind the stream
348 	 * and return the handle.
349 	 */
350 	if (debug)
351 		(void) printf("ISO 9660 header is sane.\n");
352 	h->bstr_rewind(h);
353 	return (h);
354 }
355 
356 bstreamhandle
357 open_stdin_read_stream(void)
358 {
359 	bstreamhandle h;
360 	int mode;
361 
362 	str_errno = 0;
363 	if ((mode = fcntl(0, F_GETFD, NULL)) < 0) {
364 		str_errno = STR_ERR_NO_READ_STDIN;
365 		return (NULL);
366 	}
367 	mode &= 3;
368 	if ((mode != O_RDONLY) && (mode != O_RDWR)) {
369 		str_errno = STR_ERR_NO_READ_STDIN;
370 		return (NULL);
371 	}
372 	h = (bstreamhandle)my_zalloc(sizeof (*h));
373 	h->bstr_fd = 0;
374 	h->bstr_read = file_stream_read;
375 	h->bstr_close = stdin_stream_close;
376 	h->bstr_size = file_stream_size;
377 	h->bstr_rewind = stdin_stream_rewind;
378 
379 	return (h);
380 }
381 
382 bstreamhandle
383 open_au_read_stream(char *fname)
384 {
385 	bstreamhandle h;
386 	int fd, sav;
387 	au_filehdr_t *au;
388 	struct stat st;
389 	uint32_t data_size;
390 
391 	au = NULL;
392 	str_errno = 0;
393 	fd = open(fname, O_RDONLY);
394 	if (fd < 0)
395 		return (NULL);
396 
397 	if (fstat(fd, &st) < 0) {
398 		goto au_open_failed;
399 	}
400 	if ((st.st_mode & S_IFMT) != S_IFREG) {
401 		str_errno = STR_ERR_NO_REG_FILE;
402 		goto au_open_failed;
403 	}
404 	au = (au_filehdr_t *)my_zalloc(sizeof (*au));
405 	if (read(fd, au, sizeof (*au)) != sizeof (*au)) {
406 		str_errno = STR_ERR_AU_READ_ERR;
407 		goto au_open_failed;
408 	}
409 	au->au_magic = BE32_TO_CPU(au->au_magic);
410 	au->au_offset = BE32_TO_CPU(au->au_offset);
411 	au->au_data_size = BE32_TO_CPU(au->au_data_size);
412 	au->au_encoding = BE32_TO_CPU(au->au_encoding);
413 	au->au_sample_rate = BE32_TO_CPU(au->au_sample_rate);
414 	au->au_channels = BE32_TO_CPU(au->au_channels);
415 
416 	if (au->au_magic != AUDIO_AU_FILE_MAGIC) {
417 		str_errno = STR_ERR_AU_BAD_HEADER;
418 		goto au_open_failed;
419 	}
420 	if ((au->au_encoding != AUDIO_AU_ENCODING_LINEAR_16) ||
421 	    (au->au_sample_rate != 44100) || (au->au_channels != 2)) {
422 
423 		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
424 		goto au_open_failed;
425 	}
426 	if (au->au_data_size != AUDIO_AU_UNKNOWN_SIZE) {
427 		if ((au->au_offset + au->au_data_size) != st.st_size) {
428 			str_errno = STR_ERR_AU_BAD_HEADER;
429 			goto au_open_failed;
430 		}
431 		data_size = au->au_data_size;
432 	} else {
433 		data_size = st.st_size - au->au_offset;
434 	}
435 	if (data_size == 0) {
436 		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
437 		goto au_open_failed;
438 	}
439 	if (lseek(fd, au->au_offset, SEEK_SET) < 0) {
440 		goto au_open_failed;
441 	}
442 
443 	free(au);
444 	h = (bstreamhandle)my_zalloc(sizeof (*h));
445 	h->bstr_fd = fd;
446 	h->bstr_read = file_stream_read_wrbo;
447 	h->bstr_close = file_stream_close;
448 	h->bstr_size = audio_stream_size;
449 	h->bstr_rewind = au_stream_rewind;
450 	h->bstr_private = (void *)data_size;
451 
452 	return (h);
453 
454 au_open_failed:
455 	sav = errno;
456 	(void) close(fd);
457 	if (au != NULL)
458 		free(au);
459 	errno = sav;
460 	return (NULL);
461 }
462 
463 bstreamhandle
464 open_wav_read_stream(char *fname)
465 {
466 	bstreamhandle h;
467 	int fd, sav;
468 	Wave_filehdr *wav;
469 	struct stat st;
470 	uint32_t data_size;
471 
472 	wav = NULL;
473 	str_errno = 0;
474 	fd = open(fname, O_RDONLY);
475 	if (fd < 0)
476 		return (NULL);
477 
478 	if (fstat(fd, &st) < 0) {
479 		goto wav_open_failed;
480 	}
481 	if ((st.st_mode & S_IFMT) != S_IFREG) {
482 		str_errno = STR_ERR_NO_REG_FILE;
483 		goto wav_open_failed;
484 	}
485 	wav = (Wave_filehdr *)my_zalloc(sizeof (*wav));
486 	if (read(fd, wav, sizeof (*wav)) != sizeof (*wav)) {
487 		str_errno = STR_ERR_WAV_READ_ERR;
488 		goto wav_open_failed;
489 	}
490 	if ((strncmp(wav->riff, "RIFF", 4) != 0) ||
491 		(strncmp(wav->wave, "WAVE", 4) != 0)) {
492 		str_errno = STR_ERR_WAV_BAD_HEADER;
493 		goto wav_open_failed;
494 	}
495 	if (((CPU_TO_LE32(wav->total_chunk_size) + 8) != st.st_size) ||
496 	    (strncmp(wav->fmt, "fmt ", 4) != 0) ||
497 	    (CPU_TO_LE16(wav->fmt_tag) != 1) ||
498 	    (CPU_TO_LE16(wav->n_channels) != 2) ||
499 	    (CPU_TO_LE32(wav->sample_rate) != 44100) ||
500 	    (CPU_TO_LE16(wav->bits_per_sample) != 16) ||
501 	    (strncmp(wav->data, "data", 4) != 0) ||
502 	    ((CPU_TO_LE32(wav->data_size) + 44) != st.st_size)) {
503 
504 		str_errno = STR_ERR_WAV_UNSUPPORTED_FORMAT;
505 		goto wav_open_failed;
506 	}
507 	data_size = CPU_TO_LE32(wav->data_size);
508 	if (lseek(fd, sizeof (*wav), SEEK_SET) < 0) {
509 		goto wav_open_failed;
510 	}
511 
512 	free(wav);
513 	h = (bstreamhandle)my_zalloc(sizeof (*h));
514 	h->bstr_fd = fd;
515 	h->bstr_read = file_stream_read;
516 	h->bstr_close = file_stream_close;
517 	h->bstr_size = audio_stream_size;
518 	h->bstr_rewind = wav_stream_rewind;
519 	h->bstr_private = (void *)data_size;
520 
521 	return (h);
522 
523 wav_open_failed:
524 	sav = errno;
525 	(void) close(fd);
526 	if (wav != NULL)
527 		free(wav);
528 	errno = sav;
529 	return (NULL);
530 }
531 
532 bstreamhandle
533 open_aur_read_stream(char *fname)
534 {
535 	bstreamhandle h;
536 
537 	h = open_file_read_stream(fname);
538 	if (h != NULL) {
539 		h->bstr_read = file_stream_read_wrbo;
540 	}
541 	return (h);
542 }
543 
544 bstreamhandle
545 open_au_write_stream(char *fname)
546 {
547 	bstreamhandle h;
548 	int esav, fd;
549 	uchar_t head[] = PRE_DEF_AU_HDR;
550 
551 	str_errno = 0;
552 	fd = -1;
553 	/* O_RDWR because we need to read while closing */
554 	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
555 	if (fd < 0)
556 		goto open_au_write_stream_failed;
557 	if (write(fd, head, PRE_DEF_AU_HDR_LEN) != PRE_DEF_AU_HDR_LEN) {
558 		goto open_au_write_stream_failed;
559 	}
560 	h = (bstreamhandle)my_zalloc(sizeof (*h));
561 	h->bstr_fd = fd;
562 	h->bstr_write = file_stream_write_wrbo;
563 	h->bstr_close = au_write_stream_close;
564 	return (h);
565 
566 open_au_write_stream_failed:
567 	esav = errno;
568 	if (fd != -1)
569 		(void) close(fd);
570 	errno = esav;
571 	return (NULL);
572 }
573 
574 bstreamhandle
575 open_wav_write_stream(char *fname)
576 {
577 	bstreamhandle h;
578 	int esav, fd;
579 	uchar_t head[] = PRE_DEF_WAV_HDR;
580 
581 	str_errno = 0;
582 	fd = -1;
583 	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
584 	if (fd < 0)
585 		goto open_wav_write_stream_failed;
586 	if (write(fd, head, PRE_DEF_WAV_HDR_LEN) != PRE_DEF_WAV_HDR_LEN) {
587 		goto open_wav_write_stream_failed;
588 	}
589 	h = (bstreamhandle)my_zalloc(sizeof (*h));
590 	h->bstr_fd = fd;
591 	h->bstr_write = file_stream_write;
592 	h->bstr_close = wav_write_stream_close;
593 	return (h);
594 
595 open_wav_write_stream_failed:
596 	esav = errno;
597 	if (fd != -1)
598 		(void) close(fd);
599 	errno = esav;
600 	return (NULL);
601 }
602 
603 bstreamhandle
604 open_aur_write_stream(char *fname)
605 {
606 	bstreamhandle h;
607 	int fd;
608 
609 	str_errno = 0;
610 	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
611 	if (fd < 0)
612 		return (NULL);
613 	h = (bstreamhandle)my_zalloc(sizeof (*h));
614 	h->bstr_fd = fd;
615 	h->bstr_write = file_stream_write_wrbo;
616 	h->bstr_close = file_stream_close;
617 	return (h);
618 }
619 
620 bstreamhandle
621 open_file_write_stream(char *fname)
622 {
623 	bstreamhandle h;
624 	int fd;
625 
626 	str_errno = 0;
627 	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
628 	if (fd < 0)
629 		return (NULL);
630 	h = (bstreamhandle)my_zalloc(sizeof (*h));
631 	h->bstr_fd = fd;
632 	h->bstr_write = file_stream_write;
633 	h->bstr_close = file_stream_close;
634 	return (h);
635 }
636 
637 bstreamhandle
638 open_temp_file_stream(void)
639 {
640 	bstreamhandle h;
641 	char *t;
642 	int fd;
643 
644 	str_errno = 0;
645 
646 	t = (char *)get_tmp_name();
647 
648 	if (strlcat(t, "/cdXXXXXX", PATH_MAX) >= PATH_MAX)
649 		return (NULL);
650 
651 	fd = mkstemp(t);
652 
653 	if (debug)
654 		(void) printf("temp is: %s length: %d\n", t, strlen(t));
655 
656 	if (fd < 0)
657 		return (NULL);
658 	(void) unlink(t);
659 
660 	h = (bstreamhandle)my_zalloc(sizeof (*h));
661 	h->bstr_fd = fd;
662 	h->bstr_read = file_stream_read;
663 	h->bstr_write = file_stream_write;
664 	h->bstr_close = file_stream_close;
665 	h->bstr_size = file_stream_size;
666 	h->bstr_rewind = file_stream_rewind;
667 
668 	return (h);
669 }
670 
671 /*
672  * check_avail_temp_space returns 0 if there is adequate space
673  * in the temporary directory, or a non-zero error code if
674  * something goes wrong
675  */
676 int
677 check_avail_temp_space(size_t req_size)
678 {
679 	struct statvfs buf;
680 	u_longlong_t free_size = 0;
681 
682 	if (statvfs(get_tmp_name(), &buf) < 0) {
683 		return (errno);
684 	}
685 
686 	free_size = buf.f_bfree * buf.f_frsize;
687 
688 	if (free_size <= req_size)
689 		return (ENOMEM);
690 
691 	return (0);
692 }
693 
694 
695 char *
696 get_tmp_name(void)
697 {
698 	char *t;
699 	char *envptr;
700 
701 	t = (char *)my_zalloc(PATH_MAX);
702 
703 	/*
704 	 * generate temp directory path based on this order:
705 	 * user specified (-m option), temp env variable,
706 	 * and finally /tmp if nothing is found.
707 	 */
708 
709 	if (alt_tmp_dir) {
710 
711 		/* copy and leave room for temp filename */
712 
713 		(void) strlcpy(t, alt_tmp_dir, PATH_MAX - 10);
714 	} else {
715 		envptr = getenv("TMPDIR");
716 		if (envptr != NULL) {
717 			(void) strlcpy(t, envptr, PATH_MAX - 10);
718 		} else {
719 			(void) strlcpy(t, "/tmp", 5);
720 		}
721 	}
722 
723 	/*
724 	 * no need to check if path is valid. statvfs will catch
725 	 * it later and fail with a proper error message.
726 	 */
727 
728 	return (t);
729 }
730