if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
/* Ask FS to truncate the file */
- if ((r = forbidden(fp, vp, W_BIT)) == OK)
- r = truncate_vnode(vp, length);
+ if ((r = forbidden(fp, vp, W_BIT)) == OK) {
+ /* If the file size does not change, do not make the actual call. This
+ * ensures that the file times are retained when the file size remains
+ * the same, which is a POSIX requirement.
+ */
+ if (S_ISREG(vp->v_mode) && vp->v_size == length)
+ r = OK;
+ else
+ r = truncate_vnode(vp, length);
+ }
unlock_vnode(vp);
unlock_vmnt(vmp);
{
/* As with do_truncate(), truncate_vnode() does the actual work. */
struct filp *rfilp;
+ struct vnode *vp;
int r;
off_t length;
if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_WRITE)) == NULL)
return(err_code);
+ vp = rfilp->filp_vno;
+
if (!(rfilp->filp_mode & W_BIT))
r = EBADF;
+ else if (S_ISREG(vp->v_mode) && vp->v_size == length)
+ /* If the file size does not change, do not make the actual call. This
+ * ensures that the file times are retained when the file size remains
+ * the same, which is a POSIX requirement.
+ */
+ r = OK;
else
- r = truncate_vnode(rfilp->filp_vno, length);
+ r = truncate_vnode(vp, length);
unlock_filp(rfilp);
return(r);
assert(tll_locked_by_me(&vp->v_lock));
file_type = vp->v_mode & I_TYPE;
if (file_type != I_REGULAR && file_type != I_NAMED_PIPE) return(EINVAL);
+
+ /* We must not compare the old and the new size here: this function may be
+ * called for open(2), which requires an update to the file times if O_TRUNC
+ * is given, even if the file size remains the same.
+ */
if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) == OK)
vp->v_size = newsize;
return(r);
if (yc != pc) e(39);
if (ym != pm) e(40);
if (close(fd) != 0) e(41);
+ /* Try once more, now without changing the file size. */
+ sleep(1);
+ if ( (fd = open("T16.e", O_WRONLY|O_TRUNC)) < 0) e(89);
+ get_times("T16.e", &a, &c, &m);
+ if (c != m) e(90);
+ if (c == xc) e(91);
+ if (m == xm) e(92);
+ if (close(fd) != 0) e(93);
/* Test the times for link/unlink. */
get_times("T16.e", &a, &c, &m);