static int
add_mtab(char *devname, char *mountpoint, unsigned long flags, const char *fstype)
{
- int rc = 0;
+ int rc = 0, tmprc, fd;
uid_t uid;
char *mount_user = NULL;
struct mntent mountent;
+ struct stat statbuf;
FILE *pmntfile;
sigset_t mask, oldmask;
goto add_mtab_exit;
}
+ fd = fileno(pmntfile);
+ if (fd < 0) {
+ fprintf(stderr, "mntent does not appear to be valid\n");
+ unlock_mtab();
+ rc = EX_FILEIO;
+ goto add_mtab_exit;
+ }
+
+ rc = fstat(fd, &statbuf);
+ if (rc != 0) {
+ fprintf(stderr, "unable to fstat open mtab\n");
+ endmntent(pmntfile);
+ unlock_mtab();
+ rc = EX_FILEIO;
+ goto add_mtab_exit;
+ }
+
mountent.mnt_fsname = devname;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = (char *)(void *)fstype;
rc = addmntent(pmntfile, &mountent);
if (rc) {
fprintf(stderr, "unable to add mount entry to mtab\n");
+ ftruncate(fd, statbuf.st_size);
+ rc = EX_FILEIO;
+ }
+ tmprc = my_endmntent(pmntfile, statbuf.st_size);
+ if (tmprc) {
+ fprintf(stderr, "error %d detected on close of mtab\n", tmprc);
rc = EX_FILEIO;
}
- endmntent(pmntfile);
unlock_mtab();
SAFE_FREE(mountent.mnt_opts);
add_mtab_exit:
extern int mtab_unusable(void);
extern int lock_mtab(void);
extern void unlock_mtab(void);
+extern int my_endmntent(FILE *stream, off_t size);
#endif /* ! _MOUNT_H_ */
return 0;
}
+/*
+ * Call fflush and fsync on the mtab, and then endmntent. If either fflush
+ * or fsync fails, then truncate the file back to "size". endmntent is called
+ * unconditionally, and the errno (if any) from fflush and fsync are returned.
+ */
+int
+my_endmntent(FILE *stream, off_t size)
+{
+ int rc, fd;
+
+ fd = fileno(stream);
+ if (fd < 0)
+ return -EBADF;
+
+ rc = fflush(stream);
+ if (!rc)
+ rc = fsync(fd);
+
+ /* truncate file back to "size" -- best effort here */
+ if (rc) {
+ rc = errno;
+ ftruncate(fd, size);
+ }
+
+ endmntent(stream);
+ return rc;
+}