2 * Copyright (c) 1980, 1986 The Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #include <afsconfig.h>
19 #include <afs/param.h>
22 /* We need the old directory type headers (included below), so don't include
23 * the normal dirent.h, or it will conflict. */
25 # include <sys/inode.h>
26 # define LONGFILENAMES 1
27 # include <sys/sysmacros.h>
29 # include <sys/signal.h>
31 # ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
32 # include </usr/old/usr/include/ndir.h>
42 #define VICE /* allow us to put our changes in at will */
44 #include <sys/vnode.h>
45 #include <sys/mount.h>
46 #include <ufs/inode.h>
54 #else /* AFS_OSF_ENV */
55 #ifdef AFS_VFSINCL_ENV
56 #include <sys/vnode.h>
58 #include <sys/fs/ufs_inode.h>
59 #include <sys/fs/ufs_fs.h>
61 #include <sys/fs/ufs_fsdir.h>
63 #include <sys/fs/ufs_mount.h>
65 #include <ufs/inode.h>
67 #include <ufs/fsdir.h>
69 #else /* AFS_VFSINCL_ENV */
70 #include <sys/inode.h>
75 #endif /* AFS_VFSINCL_ENV */
76 #endif /* AFS_OSF_ENV */
80 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV)
86 long diskreads
, totalreads
; /* Disk cache statistics */
87 #if !defined(AFS_HPUX101_ENV)
90 #if defined(AFS_SUN_ENV)
97 #include <sys/mntent.h>
98 #include <sys/mnttab.h>
99 #include <sys/vfstab.h>
107 switch (dp
->di_mode
& IFMT
) {
129 printf("bad file type 0%o\n", dp
->di_mode
);
144 pfatal("INTERNAL ERROR: GOT TO reply()");
145 persevere
= !strcmp(question
, "CONTINUE");
147 if (!persevere
&& (nflag
|| fswritefd
< 0)) {
148 printf("%s? no\n\n", question
);
149 #if defined(AFS_SUN_ENV)
150 iscorrupt
= 1; /* known to be corrupt */
154 if (yflag
|| (persevere
&& nflag
)) {
155 printf("%s? yes\n\n", question
);
159 printf("%s? [yn] ", question
);
160 (void)fflush(stdout
);
162 while (c
!= '\n' && getc(stdin
) != '\n')
165 } while (c
!= 'y' && c
!= 'Y' && c
!= 'n' && c
!= 'N');
167 if (c
== 'y' || c
== 'Y')
172 #if defined(AFS_SUN_ENV)
173 iscorrupt
= 1; /* known to be corrupt */
179 * Malloc buffers and set up cache.
187 bufp
= malloc((unsigned int)sblock
.fs_bsize
);
189 errexit("cannot allocate buffer pool\n");
190 cgblk
.b_un
.b_buf
= bufp
;
192 bufhead
.b_next
= bufhead
.b_prev
= &bufhead
;
193 bufcnt
= MAXBUFSPACE
/ sblock
.fs_bsize
;
194 if (bufcnt
< MINBUFS
)
196 for (i
= 0; i
< bufcnt
; i
++) {
197 bp
= malloc(sizeof(struct bufarea
));
198 bufp
= malloc((unsigned int)sblock
.fs_bsize
);
199 if (bp
== NULL
|| bufp
== NULL
) {
202 errexit("cannot allocate buffer pool\n");
204 bp
->b_un
.b_buf
= bufp
;
205 bp
->b_prev
= &bufhead
;
206 bp
->b_next
= bufhead
.b_next
;
207 bufhead
.b_next
->b_prev
= bp
;
211 bufhead
.b_size
= i
; /* save number of buffers */
218 * Manage a cache of directory blocks.
221 getdatablk(blkno
, size
)
227 for (bp
= bufhead
.b_next
; bp
!= &bufhead
; bp
= bp
->b_next
)
228 if (bp
->b_bno
== fsbtodb(&sblock
, blkno
))
230 for (bp
= bufhead
.b_prev
; bp
!= &bufhead
; bp
= bp
->b_prev
)
231 if ((bp
->b_flags
& B_INUSE
) == 0)
234 errexit("deadlocked buffer pool\n");
235 getblk(bp
, blkno
, size
);
239 bp
->b_prev
->b_next
= bp
->b_next
;
240 bp
->b_next
->b_prev
= bp
->b_prev
;
241 bp
->b_prev
= &bufhead
;
242 bp
->b_next
= bufhead
.b_next
;
243 bufhead
.b_next
->b_prev
= bp
;
245 bp
->b_flags
|= B_INUSE
;
250 getblk(bp
, blk
, size
)
257 dblk
= fsbtodb(&sblock
, blk
);
258 if (bp
->b_bno
== dblk
)
260 flush(fswritefd
, bp
);
262 bp
->b_errs
= bread(fsreadfd
, bp
->b_un
.b_buf
, dblk
, size
);
278 if (bp
->b_errs
!= 0) {
279 pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
280 (bp
->b_errs
== bp
->b_size
/ dev_bsize
) ? "" : "PARTIALLY ",
285 bwrite(fd
, bp
->b_un
.b_buf
, bp
->b_bno
, (long)bp
->b_size
);
288 #if defined(AFS_HPUX101_ENV)
289 #if defined(AFS_HPUX110_ENV)
290 /* jpm: Need a fix here */
292 #else /* AFS_HPUX110_ENV */
294 (fswritefd
, (char *)sblock
.fs_csp
[0],
295 fsbtodb(&sblock
, sblock
.fs_csaddr
), fragroundup(&sblock
,
296 sblock
.fs_cssize
)) ==
298 #endif /* else AFS_HPUX110_ENV */
301 ("\nUnable to write to cylinder group summary area (fs_csaddr)\n");
302 printf("\tDisk write error at block %u\n",
303 fsbtodb(&sblock
, sblock
.fs_csaddr
));
306 #if defined(AFS_SUN5_ENV)
307 sip
= (caddr_t
) sblock
.fs_u
.fs_csp
;
308 for (i
= 0, j
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
, j
++) {
310 sblock
.fs_cssize
- i
<
311 sblock
.fs_bsize
? sblock
.fs_cssize
- i
: sblock
.fs_bsize
;
312 bwrite(fswritefd
, sip
,
313 fsbtodb(&sblock
, sblock
.fs_csaddr
+ j
* sblock
.fs_frag
), size
);
317 for (i
= 0, j
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
, j
++) {
318 bwrite(fswritefd
, (char *)sblock
.fs_csp
[j
],
319 fsbtodb(&sblock
, sblock
.fs_csaddr
+ j
* sblock
.fs_frag
),
320 sblock
.fs_cssize
- i
<
321 sblock
.fs_bsize
? sblock
.fs_cssize
- i
: sblock
.fs_bsize
);
323 #endif /* AFS_SUN5_ENV */
324 #endif /* AFS_HPUX101_ENV */
334 pfatal("CANNOT %s: BLK %ld", mesg
, blk
);
335 if (reply("CONTINUE") == 0)
336 errexit("Program terminated\n");
341 struct bufarea
*bp
, *nbp
;
344 flush(fswritefd
, &sblk
);
346 if (havesb
&& sblk
.b_bno
!= SBOFF
/ dev_bsize
&& !preen
347 && reply("UPDATE STANDARD SUPERBLOCK")) {
348 sblk
.b_bno
= SBOFF
/ dev_bsize
;
349 #else /* AFS_NEWCG_ENV */
350 if (havesb
&& sblk
.b_bno
!= SBLOCK
&& !preen
351 && reply("UPDATE STANDARD SUPERBLOCK")) {
353 #endif /* AFS_NEWCG_ENV */
355 flush(fswritefd
, &sblk
);
357 flush(fswritefd
, &cgblk
);
358 if (cgblk
.b_un
.b_buf
) {
359 free(cgblk
.b_un
.b_buf
);
360 cgblk
.b_un
.b_buf
= NULL
;
362 for (bp
= bufhead
.b_prev
; bp
!= &bufhead
; bp
= nbp
) {
364 flush(fswritefd
, bp
);
366 free(bp
->b_un
.b_buf
);
372 if (bufhead
.b_size
!= cnt
)
373 errexit("Panic: lost %d buffers\n", bufhead
.b_size
- cnt
);
375 printf("cache missed %d of %d (%d%%)\n", diskreads
, totalreads
,
376 diskreads
* 100 / totalreads
);
377 (void)close(fsreadfd
);
378 (void)close(fswritefd
);
381 #if !defined(AFS_HPUX101_ENV)
382 bread(fd
, buf
, blk
, size
)
395 offset_t offset
= (offset_t
) blk
<< DEV_BSHIFT
;
400 /* To fix a stripping related bug?? */
401 if (lseek(fd
, blk
* dev_bsize
, 0) == -1)
404 if (llseek(fd
, offset
, 0) < 0)
406 if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
409 rwerror("SEEK", blk
);
410 else if (read(fd
, buf
, (int)size
) == size
)
412 rwerror("READ", blk
);
414 /* To fix a stripping related bug?? */
415 if (lseek(fd
, blk
* dev_bsize
, 0) == -1)
418 if (llseek(fd
, offset
, 0) < 0)
420 if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
423 rwerror("SEEK", blk
);
425 memset(buf
, 0, (int)size
);
426 printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
428 for (cp
= buf
, i
= 0; i
< btodb(size
); i
++, cp
+= DEV_BSIZE
) {
429 addr
= (offset_t
) (blk
+ i
) << DEV_BSHIFT
;
430 if (llseek(fd
, addr
, SEEK_CUR
) < 0 || read(fd
, cp
, (int)secsize
) < 0) {
431 printf(" %d", blk
+ i
);
433 for (cp
= buf
, i
= 0; i
< size
; i
+= secsize
, cp
+= secsize
) {
434 if (read(fd
, cp
, (int)secsize
) < 0) {
435 lseek(fd
, blk
* dev_bsize
+ i
+ secsize
, 0);
436 if (secsize
!= dev_bsize
&& dev_bsize
!= 1)
437 printf(" %d (%d),", (blk
* dev_bsize
+ i
) / secsize
,
438 blk
+ i
/ dev_bsize
);
440 printf(" %d,", blk
+ i
/ dev_bsize
);
449 bwrite(fd
, buf
, blk
, size
)
462 offset_t offset
= (offset_t
) blk
<< DEV_BSHIFT
;
467 sprintf(msg
, "WARNING: Attempt to write illegal blkno %d on %s\n",
478 /* To fix a stripping related bug?? */
479 if (lseek(fd
, blk
* dev_bsize
, 0) == -1)
482 if (llseek(fd
, offset
, 0) < 0)
484 if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
487 rwerror("SEEK", blk
);
488 else if (write(fd
, buf
, (int)size
) == size
) {
492 rwerror("WRITE", blk
);
494 /* To fix a stripping related bug?? */
495 if (lseek(fd
, blk
* dev_bsize
, 0) == -1)
498 if (llseek(fd
, offset
, 0) < 0)
500 if (lseek(fd
, blk
* dev_bsize
, 0) < 0)
503 rwerror("SEEK", blk
);
504 printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
506 for (cp
= buf
, i
= 0; i
< btodb(size
); i
++, cp
+= DEV_BSIZE
) {
508 addr
= (offset_t
) (blk
+ i
) << DEV_BSHIFT
;
509 if (llseek(fd
, addr
, SEEK_CUR
) < 0
510 || (n
= write(fd
, cp
, DEV_BSIZE
)) < 0) {
511 printf(" %d", blk
+ i
);
518 for (cp
= buf
, i
= 0; i
< size
; i
+= dev_bsize
, cp
+= dev_bsize
)
519 if (write(fd
, cp
, (int)dev_bsize
) < 0) {
520 lseek(fd
, blk
* dev_bsize
+ i
+ dev_bsize
, 0);
521 printf(" %d,", blk
+ i
/ dev_bsize
);
527 #endif /* AFS_HPUX101_ENV */
529 * allocate a data block with the specified number of fragments
536 if (frags
<= 0 || frags
> sblock
.fs_frag
)
538 for (i
= 0; i
< maxfsblock
- sblock
.fs_frag
; i
+= sblock
.fs_frag
) {
539 for (j
= 0; j
<= sblock
.fs_frag
- frags
; j
++) {
542 for (k
= 1; k
< frags
; k
++)
543 if (testbmap(i
+ j
+ k
))
549 for (k
= 0; k
< frags
; k
++)
559 * Free a previously allocated block
561 freeblk(blkno
, frags
)
565 struct inodesc idesc
;
567 idesc
.id_blkno
= blkno
;
568 idesc
.id_numfrags
= frags
;
575 getpathname(namebuf
, curdir
, ino
)
581 struct inodesc idesc
;
582 extern int findname();
584 if (statemap
[ino
] != DSTATE
&& statemap
[ino
] != DFOUND
) {
585 strcpy(namebuf
, "?");
588 memset(&idesc
, 0, sizeof(struct inodesc
));
589 idesc
.id_type
= DATA
;
590 cp
= &namebuf
[BUFSIZ
- 1];
593 idesc
.id_parent
= curdir
;
596 while (ino
!= ROOTINO
) {
597 idesc
.id_number
= ino
;
598 idesc
.id_func
= findino
;
599 idesc
.id_name
= "..";
601 idesc
.id_fix
= NOFIX
;
603 if ((ckinode(ginode(ino
), &idesc
) & FOUND
) == 0)
606 idesc
.id_number
= idesc
.id_parent
;
607 idesc
.id_parent
= ino
;
608 idesc
.id_func
= findname
;
609 idesc
.id_name
= namebuf
;
611 idesc
.id_fix
= NOFIX
;
613 if ((ckinode(ginode(idesc
.id_number
), &idesc
) & FOUND
) == 0)
615 len
= strlen(namebuf
);
617 if (cp
< &namebuf
[MAXNAMLEN
])
619 memcpy(cp
, namebuf
, len
);
621 ino
= idesc
.id_number
;
623 if (ino
!= ROOTINO
) {
624 strcpy(namebuf
, "?");
627 memcpy(namebuf
, cp
, &namebuf
[BUFSIZ
] - cp
);
642 * When preening, allow a single quit to signal
643 * a special exit after filesystem checks complete
644 * so that reboot sequence may be interrupted.
649 extern returntosingle
;
651 printf("returning to single-user after filesystem check\n");
653 (void)signal(SIGQUIT
, SIG_DFL
);
657 * Ignore a single quit signal; wait and flush just in case.
658 * Used by child processes in preen.
665 (void)signal(SIGQUIT
, SIG_IGN
);
666 (void)signal(SIGQUIT
, SIG_DFL
);
670 * determine whether an inode should be fixed.
673 struct inodesc
*idesc
;
677 switch (idesc
->id_fix
) {
680 if (idesc
->id_type
== DATA
)
681 direrror(idesc
->id_number
, msg
);
685 printf(" (SALVAGED)\n");
689 if (reply("SALVAGE") == 0) {
690 idesc
->id_fix
= NOFIX
;
703 errexit("UNKNOWN INODESC FIX MODE %d\n", idesc
->id_fix
);
709 errexit(s1
, s2
, s3
, s4
)
713 printf(s1
, s2
, s3
, s4
);
722 * An unexpected inconsistency occured.
723 * Die if preening, otherwise just print message and continue.
726 pfatal(s
, a1
, a2
, a3
)
731 printf("%s: ", devname
);
732 printf(s
, a1
, a2
, a3
);
734 printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname
);
741 printf(s
, a1
, a2
, a3
);
745 * Pwarn just prints a message when not preening,
746 * or a warning (preceded by filename) when preening.
749 pwarn(s
, a1
, a2
, a3
, a4
, a5
, a6
)
751 long a1
, a2
, a3
, a4
, a5
, a6
;
754 printf("%s: ", devname
);
755 printf(s
, a1
, a2
, a3
, a4
, a5
, a6
);
759 * Pwarn just prints a message when not preening,
760 * or a warning (preceded by filename) when preening.
763 pinfo(s
, a1
, a2
, a3
, a4
, a5
, a6
)
765 long a1
, a2
, a3
, a4
, a5
, a6
;
768 printf("%s: ", devname
);
769 printf(s
, a1
, a2
, a3
, a4
, a5
, a6
);
774 * Stub for routines from kernel.
780 pfatal("INTERNAL INCONSISTENCY:");
785 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
792 if ((iscorrupt
== 0) && (isdirty
== 0))
794 if ((sblock
.fs_clean
!= FSSTABLE
) && (sblock
.fs_clean
!= FSCLEAN
))
797 if (FSOKAY
!= (sblock
.fs_state
+ sblock
.fs_time
))
799 if (FSOKAY
!= (fs_get_state(&sblock
) + sblock
.fs_time
))
803 sprintf(s
, "WARNING: inconsistencies detected on `%s' filesystem %s",
804 sblock
.fs_clean
== FSSTABLE
? "stable" : "clean", devname
);
810 struct bufarea cleanbuf
;
813 unsigned int fsclean
;
814 #if defined(AFS_SUN5_ENV)
819 /* set fsclean to its appropriate value */
820 fsclean
= sblock
.fs_clean
;
822 if (FSOKAY
!= (sblock
.fs_state
+ sblock
.fs_time
))
824 if (FSOKAY
!= (fs_get_state(&sblock
) + sblock
.fs_time
))
828 /* if necessary, update fs_clean and fs_state */
845 /* if fs_clean and fs_state are ok, do nothing */
846 if ((sblock
.fs_clean
== fsclean
) &&
848 (FSOKAY
== (sblock
.fs_state
+ sblock
.fs_time
)))
850 (FSOKAY
== (fs_get_state(&sblock
) + sblock
.fs_time
)))
853 sblock
.fs_clean
= fsclean
;
855 sblock
.fs_state
= sblock
.fs_time
;
857 fs_set_state(&sblock
, sblock
.fs_time
);
859 /* if superblock can't be written, return */
862 /* read private copy of superblock, update clean flag, and write it */
865 #if defined(AFS_SUN5_ENV)
866 sblkoff
= (OFF_T
) (bno
) << DEV_BSHIFT
;
867 if (llseek(fsreadfd
, sblkoff
, 0) == -1)
870 if (lseek(fsreadfd
, (off_t
) dbtob(bno
), 0) == -1)
873 if ((cleanbuf
.b_un
.b_buf
= malloc(size
)) == NULL
)
874 errexit("out of memory");
875 if (read(fsreadfd
, cleanbuf
.b_un
.b_buf
, (int)size
) != size
)
877 cleanbuf
.b_un
.b_fs
->fs_clean
= sblock
.fs_clean
;
879 cleanbuf
.b_un
.b_fs
->fs_state
= sblock
.fs_state
;
881 fs_set_state(cleanbuf
.b_un
.b_fs
, fs_get_state(&sblock
));
883 cleanbuf
.b_un
.b_fs
->fs_time
= sblock
.fs_time
;
884 #if defined(AFS_SUN5_ENV)
885 if (llseek(fswritefd
, sblkoff
, 0) == -1)
888 if (lseek(fswritefd
, (off_t
) dbtob(bno
), 0) == -1)
891 if (write(fswritefd
, cleanbuf
.b_un
.b_buf
, (int)size
) != size
)
900 if (FSOKAY
!= (sblock
.fs_state
+ sblock
.fs_time
))
902 if (FSOKAY
!= (fs_get_state(&sblock
) + sblock
.fs_time
))
907 switch (sblock
.fs_clean
) {
921 pwarn("is %s.\n", s
);
923 printf("** %s is %s.\n", devname
, s
);
934 static char *tmpopts
;
936 if (vfs
->vfs_mntopts
== NULL
)
939 tmpopts
= calloc(256, sizeof(char));
943 strncpy(tmpopts
, vfs
->vfs_mntopts
, (sizeof(tmpopts
) - 1));
946 for (; *f
; f
= mntopt(&opts
)) {
947 if (strncmp(opt
, f
, strlen(opt
)) == 0)
948 return (f
- tmpopts
+ vfs
->vfs_mntopts
);
958 struct vfstab vfsbuf
;
960 char *blkname
, *unrawname();
962 vfstab
= fopen(VFSTAB
, "r");
963 if (vfstab
== NULL
) {
964 printf("can't open %s\n", VFSTAB
);
967 blkname
= unrawname(name
);
968 if ((getvfsspec(vfstab
, &vfsbuf
, blkname
) == 0)
969 && (vfsbuf
.vfs_fstype
!= NULL
)
970 && (strcmp(vfsbuf
.vfs_fstype
, MNTTYPE_UFS
) == 0)
971 && (hasvfsopt(&vfsbuf
, MNTOPT_RO
))) {
984 struct stat device_stat
, mount_stat
;
985 char *blkname
, *unrawname();
987 mnttab
= fopen(MNTTAB
, "r");
988 if (mnttab
== NULL
) {
989 printf("can't open %s\n", MNTTAB
);
992 blkname
= unrawname(name
);
993 while ((getmntent(mnttab
, &mnt
)) == NULL
) {
994 if (strcmp(mnt
.mnt_fstype
, MNTTYPE_UFS
) != 0) {
997 if (strcmp(blkname
, mnt
.mnt_special
) == 0) {
998 stat(mnt
.mnt_mountp
, &mount_stat
);
999 stat(mnt
.mnt_special
, &device_stat
);
1000 if (device_stat
.st_rdev
== mount_stat
.st_dev
) {
1001 if (hasmntopt(&mnt
, MNTOPT_RO
) != 0)
1002 found
= 2; /* mounted as RO */
1004 found
= 1; /* mounted as R/W */
1015 #if defined(AFS_HPUX101_ENV)
1018 #include <sys/fcntl.h>
1022 bread(fd
, buf
, blk
, size
)
1031 switch (seek_options
) {
1032 case BLKSEEK_ENABLED
:
1036 case BLKSEEK_NOT_ENABLED
: /* File */
1037 #if defined(AFS_HPUX102_ENV)
1038 lseek_offset
= dbtoo(blk
);
1040 lseek_offset
= dbtob(blk
);
1045 rwerror("BLKSEEK", blk
);
1047 if (lseek(fd
, (off_t
) lseek_offset
, 0) == (off_t
) - 1)
1048 rwerror("SEEK", blk
);
1049 else if (read(fd
, buf
, (int)size
) == size
)
1051 rwerror("READ", blk
);
1055 bwrite(fd
, buf
, blk
, size
)
1066 switch (seek_options
) {
1067 case BLKSEEK_ENABLED
:
1071 case BLKSEEK_NOT_ENABLED
: /* File */
1072 #if defined(AFS_HPUX102_ENV)
1073 lseek_offset
= dbtoo(blk
);
1075 lseek_offset
= dbtob(blk
);
1080 rwerror("BLKSEEK", blk
);
1082 if (lseek(fd
, (off_t
) lseek_offset
, 0) == (off_t
) - 1)
1083 rwerror("SEEK", blk
);
1084 else if (write(fd
, buf
, (int)size
) == size
) {
1088 rwerror("WRITE", blk
);
1093 setup_block_seek(fd
)
1094 int fd
; /* File descriptor */
1096 int flags
= 0; /* Flags to/from fcntl() */
1098 return setup_block_seek_2(fd
, &flags
);
1101 #define set_fserror printf
1104 setup_block_seek_2(fd
, cntl_flags
)
1105 int fd
; /* Input. File descriptor */
1106 int *cntl_flags
; /* Returned. Flags from fcntl() */
1108 int flags
= 0; /* Flags to/from fcntl() */
1109 off_t lstatus
; /* Status from lseek() */
1110 struct stat statarea
;
1111 char dummy
[MAXBSIZE
];
1117 if ((flags
= fcntl(fd
, F_GETFL
)) == -1) {
1118 set_fserror("Cannot get file control flags.");
1119 return (BLKSEEK_PROCESSING_ERROR
);
1123 * Check if fd is a non-device file
1126 if (fstat(fd
, &statarea
) == -1) {
1127 set_fserror("Cannot get status information on file descriptor.");
1128 return (BLKSEEK_PROCESSING_ERROR
);
1130 if (((statarea
.st_mode
& S_IFMT
) != S_IFCHR
)
1131 && ((statarea
.st_mode
& S_IFMT
) != S_IFBLK
)) {
1132 /* Not a device file -- BLKSEEK only works on device files */
1133 *cntl_flags
= flags
; /* O_BLKSEEK bit never set */
1134 return (BLKSEEK_NOT_ENABLED
);
1138 * Set the fd to O_BLKSEEK
1140 if (fcntl(fd
, F_SETFL
, flags
| O_BLKSEEK
) == -1) {
1141 set_fserror("Cannot set file control flags.");
1142 return (BLKSEEK_PROCESSING_ERROR
);
1144 if (flags
& O_WRONLY
) {
1145 /* Set lseek to location 0 before returning */
1146 if (lseek(fd
, (off_t
) 0, SEEK_SET
) == (off_t
) - 1) {
1147 set_fserror("Cannot lseek the device.");
1148 return (BLKSEEK_PROCESSING_ERROR
);
1152 ("File is write only. Cannot Verify O_BLKSEEK mode set.");
1153 *cntl_flags
= flags
| O_BLKSEEK
;
1154 return (BLKSEEK_FILE_WRITEONLY
);
1158 * Verify that kernel knows how to do O_BLKSEEK
1160 if (lseek(fd
, (off_t
) 0, SEEK_SET
) == (off_t
) - 1) {
1161 set_fserror("Cannot lseek the device.");
1162 return (BLKSEEK_PROCESSING_ERROR
);
1164 if (read(fd
, &dummy
[0], BBSIZE
) != BBSIZE
) { /* BBSIZE = 8192 */
1165 set_fserror("Cannot read from the device");
1166 return (BLKSEEK_PROCESSING_ERROR
);
1169 if ((lstatus
= lseek(fd
, (off_t
) 0, SEEK_CUR
)) == (off_t
) - 1) {
1170 set_fserror("Cannot lseek the device.");
1171 return (BLKSEEK_PROCESSING_ERROR
);
1175 * Set lseek to location 0
1177 if (lseek(fd
, (off_t
) 0, SEEK_SET
) == (off_t
) - 1) {
1178 set_fserror("Cannot lseek the device.");
1179 return (BLKSEEK_PROCESSING_ERROR
);
1182 if (lstatus
== (off_t
) (BBSIZE
/ DEV_BSIZE
)) {
1183 *cntl_flags
= flags
| O_BLKSEEK
;
1184 return (BLKSEEK_ENABLED
); /* Successfully enabled O_BLKSEEK */
1186 *cntl_flags
= flags
& (~O_BLKSEEK
); /* Turn off O_BLKSEEK bit */
1187 return (BLKSEEK_NOT_ENABLED
); /* O_BLKSEEK not enabled */
1190 setup_all_block_seek()
1193 seek_options
= setup_block_seek(fsreadfd
);
1194 switch (seek_options
) {
1195 case BLKSEEK_ENABLED
:
1196 case BLKSEEK_NOT_ENABLED
:
1199 errexit("setup_block_seek on fsreadfd");
1202 if (fswritefd
== -1)
1204 switch (opt
= setup_block_seek(fswritefd
)) {
1205 case BLKSEEK_FILE_WRITEONLY
: /* WO block or char device. */
1206 case BLKSEEK_NOT_ENABLED
: /* regular file. */
1207 if (seek_options
!= opt
)
1209 ("seek_options on fsreadfd (%d) and fswritefd (%d) do not match",
1213 errexit("setup_block_seek on fswritefd");
1218 printf("read option = %d write option = %d\n", seek_options
, opt
);
1223 #endif /* AFS_HPUX101_ENV */