int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) { int ret; SMB_STRUCT_STAT st; SMB_OFF_T offset; size_t total; size_t num_to_write; ssize_t pwrite_ret; release_level_2_oplocks_on_change(fsp); ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); if (ret == -1) { return ret; } if (len <= st.st_size) { return 0; } DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size))); flush_write_cache(fsp, SIZECHANGE_FLUSH); if (!sparse_buf) { sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); if (!sparse_buf) { errno = ENOMEM; return -1; } }
int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) { int ret; release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); if (len > 0 && len < 0x1000000) { if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) { set_filelen_write_cache(fsp, len); notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES, fsp->fsp_name); } }else ret=0; return ret; }
ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) { write_cache *wcp = fsp->wcp; ssize_t total_written = 0; int write_path = -1; if (fsp->print_file) { #ifdef AVM_NO_PRINTING errno = EBADF; return -1; #else fstring sharename; uint32 jobid; if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) { DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n", (unsigned int)fsp->rap_print_jobid )); errno = EBADF; return -1; } return print_job_write(SNUM(fsp->conn), jobid, data, pos, n); #endif /* AVM_NO_PRINTING */ } if (!fsp->can_write) { errno = EPERM; return(0); } if (!fsp->modified) { SMB_STRUCT_STAT st; fsp->modified = True; if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); } /* * If this is the first write and we have an exclusive oplock then setup * the write cache. */ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { setup_write_cache(fsp, st.st_size); wcp = fsp->wcp; } } } #ifdef WITH_PROFILE DO_PROFILE_INC(writecache_total_writes); if (!fsp->oplock_type) { DO_PROFILE_INC(writecache_non_oplock_writes); } #endif /* * If this file is level II oplocked then we need * to grab the shared memory lock and inform all * other files with a level II lock that they need * to flush their read caches. We keep the lock over * the shared memory area whilst doing this. */ release_level_2_oplocks_on_change(fsp); #ifdef WITH_PROFILE if (profile_p && profile_p->writecache_total_writes % 500 == 0) { DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", profile_p->writecache_init_writes, profile_p->writecache_abutted_writes, profile_p->writecache_total_writes, profile_p->writecache_non_oplock_writes, profile_p->writecache_allocated_write_caches, profile_p->writecache_num_write_caches, profile_p->writecache_direct_writes, profile_p->writecache_num_perfect_writes, profile_p->writecache_read_hits )); DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", profile_p->writecache_flushed_writes[SEEK_FLUSH], profile_p->writecache_flushed_writes[READ_FLUSH], profile_p->writecache_flushed_writes[WRITE_FLUSH], profile_p->writecache_flushed_writes[READRAW_FLUSH], profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH], profile_p->writecache_flushed_writes[CLOSE_FLUSH], profile_p->writecache_flushed_writes[SYNC_FLUSH] )); }
int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) { int ret; SMB_STRUCT_STAT st; connection_struct *conn = fsp->conn; SMB_BIG_UINT space_avail; SMB_BIG_UINT bsize,dfree,dsize; release_level_2_oplocks_on_change(fsp); /* * Actually try and commit the space on disk.... */ DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len )); /* Foxconn removed start pling 11/18/2009 */ /* Don't check negative length, to avoid "disk full" error * when copy file from Vista/Win7 to USB. */ #if 0 if (((SMB_OFF_T)len) < 0) { DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name )); errno = EINVAL; return -1; } #endif /* Foxconn removed end pling 11/18/2009 */ ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); if (ret == -1) return ret; if (len == (SMB_BIG_UINT)st.st_size) return 0; if (len < (SMB_BIG_UINT)st.st_size) { /* Shrink - use ftruncate. */ DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; } /* Grow - we need to test if we have enough space. */ if (!lp_strict_allocate(SNUM(fsp->conn))) return 0; len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); if (space_avail == (SMB_BIG_UINT)-1) { return -1; } DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); if (len > space_avail) { errno = ENOSPC; return -1; } return 0; }