void mark_file_modified(files_struct *fsp)
{
	int dosmode;

	if (fsp->modified) {
		return;
	}

	fsp->modified = true;

	if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
		return;
	}
	trigger_write_time_update(fsp);

	if (fsp->posix_open) {
		return;
	}
	if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
	      MAP_ARCHIVE(fsp->conn))) {
		return;
	}

	dosmode = dos_mode(fsp->conn, fsp->fsp_name);
	if (IS_DOS_ARCHIVE(dosmode)) {
		return;
	}
	file_set_dosmode(fsp->conn, fsp->fsp_name,
			 dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false);
}
Example #2
0
ssize_t write_file(struct smb_request *req,
			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) {
		uint32_t t;
		int ret;

		ret = print_spool_write(fsp, data, n, pos, &t);
		if (ret) {
			errno = ret;
			return -1;
		}
		return t;
	}

	if (!fsp->can_write) {
		errno = EPERM;
		return -1;
	}

	if (!fsp->modified) {
		fsp->modified = True;

		if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == 0) {
			trigger_write_time_update(fsp);
			if (!fsp->posix_open &&
					(lp_store_dos_attributes(SNUM(fsp->conn)) ||
					MAP_ARCHIVE(fsp->conn))) {
				int dosmode = dos_mode(fsp->conn, fsp->fsp_name);
				if (!IS_DOS_ARCHIVE(dosmode)) {
					file_set_dosmode(fsp->conn, fsp->fsp_name,
						 dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, 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,
						 fsp->fsp_name->st.st_ex_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.
	 */

	/* This should actually be improved to span the write. */
	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);

#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] ));
	}