Example #1
0
static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos, size_t n)
{
    ssize_t ret;

    if (pos == -1) {
        ret = vfs_write_data(fsp, data, n);
    } else {
        fsp->fh->pos = pos;
        if (pos && lp_strict_allocate(SNUM(fsp->conn))) {
            if (vfs_fill_sparse(fsp, pos) == -1) {
                return -1;
            }
        }
        ret = vfs_pwrite_data(fsp, data, n, pos);
    }

    DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
              fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));

    if (ret != -1) {
        fsp->fh->pos += ret;

        /*
         * It turns out that setting the last write time from a Windows
         * client stops any subsequent writes from updating the write time.
         * Doing this after the write gives a race condition here where
         * a stat may see the changed write time before we reset it here,
         * but it's cheaper than having to store the write time in shared
         * memory and look it up using dev/inode across all running smbd's.
         * The 99% solution will hopefully be good enough in this case. JRA.
         */

        if (fsp->pending_modtime) {
            set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime);

            /* If we didn't get the "set modtime" call ourselves, we must
               store the last write time to restore on close. JRA. */
            if (!fsp->pending_modtime_owner) {
                fsp->last_write_time = time(NULL);
            }
        }

        /* Yes - this is correct - writes don't update this. JRA. */
        /* Found by Samba4 tests. */
#if 0
        fsp->position_information = fsp->pos;
#endif
    }

    return ret;
}
Example #2
0
static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
{
	NTSTATUS status = NT_STATUS_OK;
	NTSTATUS saved_status1 = NT_STATUS_OK;
	NTSTATUS saved_status2 = NT_STATUS_OK;
	NTSTATUS saved_status3 = NT_STATUS_OK;
	connection_struct *conn = fsp->conn;

	if (fsp->aio_write_behind) {
		/*
	 	 * If we're finishing write behind on a close we can get a write
		 * error here, we must remember this.
		 */
		int ret = wait_for_aio_completion(fsp);
		if (ret) {
			saved_status1 = map_nt_error_from_unix(ret);
		}
	} else {
		cancel_aio_by_fsp(fsp);
	}
 
	/*
	 * If we're flushing on a close we can get a write
	 * error here, we must remember this.
	 */

	saved_status2 = close_filestruct(fsp);

	if (fsp->print_file) {
		print_fsp_end(fsp, close_type);
		file_free(fsp);
		return NT_STATUS_OK;
	}

	/* If this is an old DOS or FCB open and we have multiple opens on
	   the same handle we only have one share mode. Ensure we only remove
	   the share mode on the last close. */

	if (fsp->fh->ref_count == 1) {
		/* Should we return on error here... ? */
		saved_status3 = close_remove_share_mode(fsp, close_type);
	}

	if(fsp->oplock_type) {
		release_file_oplock(fsp);
	}

	locking_close_file(fsp);

	status = fd_close(conn, fsp);

	/* check for magic scripts */
	if (close_type == NORMAL_CLOSE) {
		check_magic(fsp,conn);
	}

	/*
	 * Ensure pending modtime is set after close.
	 */

	if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
		set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
	} else if (!null_timespec(fsp->last_write_time)) {
		set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
	}

	if (NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_IS_OK(saved_status1)) {
			status = saved_status1;
		} else if (!NT_STATUS_IS_OK(saved_status2)) {
			status = saved_status2;
		} else if (!NT_STATUS_IS_OK(saved_status3)) {
			status = saved_status3;
		}
	}

	DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
		conn->user,fsp->fsp_name,
		conn->num_files_open,
		nt_errstr(status) ));

	file_free(fsp);
	return status;
}
Example #3
0
int decompress_file(void)
{
	FILE *in = NULL, *out = NULL;
	unsigned char *inbuf = NULL, *outbuf = NULL;
	size_t inbuf_size, outbuf_size;
	struct inflate_state state;
	struct isal_gzip_header gz_hdr;
	const int terminal = 0, implicit = 1, stripped = 2;
	int ret = 0, success = 0, outfile_type = terminal;

	char *infile_name = global_options.infile_name, *outfile_name =
	    global_options.outfile_name;
	char *suffix = global_options.suffix;
	size_t infile_name_len = global_options.infile_name_len;
	size_t outfile_name_len = global_options.outfile_name_len;
	size_t suffix_len = global_options.suffix_len;
	int suffix_index = 0;
	uint32_t file_time;

	if (infile_name_len == stdin_file_name_len &&
	    memcmp(infile_name, stdin_file_name, infile_name_len) == 0) {
		infile_name = NULL;
		infile_name_len = 0;
	}

	if (outfile_name == NULL && !global_options.use_stdout) {
		if (infile_name != NULL) {
			outfile_type = stripped;
			while (suffix_index <
			       sizeof(default_suffixes) / sizeof(*default_suffixes)) {
				if (suffix == NULL) {
					suffix = default_suffixes[suffix_index];
					suffix_len = default_suffixes_lens[suffix_index];
					suffix_index++;
				}

				outfile_name_len = infile_name_len - suffix_len;
				if (infile_name_len >= suffix_len
				    && memcmp(infile_name + outfile_name_len, suffix,
					      suffix_len) == 0)
					break;
				suffix = NULL;
				suffix_len = 0;
			}

			if (suffix == NULL && global_options.test == NO_TEST) {
				log_print(ERROR, "igzip: %s: unknown suffix -- ignored\n",
					  infile_name);
				return 1;
			}
		}
		if (global_options.name == YES_NAME) {
			outfile_name_len = 0;
			outfile_type = implicit;
		}
		if (outfile_type != terminal)
			outfile_name = malloc_safe(outfile_name_len >=
						   MAX_FILEPATH_BUF ? outfile_name_len +
						   1 : MAX_FILEPATH_BUF);
	}

	open_in_file(&in, infile_name);
	if (in == NULL)
		goto decompress_file_cleanup;

	file_time = get_posix_filetime(in);

	inbuf_size = BLOCK_SIZE;
	outbuf_size = BLOCK_SIZE;

	inbuf = malloc_safe(inbuf_size);
	outbuf = malloc_safe(outbuf_size);

	isal_gzip_header_init(&gz_hdr);
	if (outfile_type == implicit) {
		gz_hdr.name = outfile_name;
		gz_hdr.name_buf_len = MAX_FILEPATH_BUF;
	}

	isal_inflate_init(&state);
	state.crc_flag = ISAL_GZIP_NO_HDR_VER;
	state.next_in = inbuf;
	state.avail_in = fread_safe(state.next_in, 1, inbuf_size, in, infile_name);

	ret = isal_read_gzip_header(&state, &gz_hdr);
	if (ret != ISAL_DECOMP_OK) {
		log_print(ERROR, "igzip: Error invalid gzip header found for file %s\n",
			  infile_name);
		goto decompress_file_cleanup;
	}

	if (outfile_type == implicit)
		file_time = gz_hdr.time;

	if (outfile_type == stripped || (outfile_type == implicit && outfile_name[0] == 0)) {
		outfile_name_len = infile_name_len - suffix_len;
		memcpy(outfile_name, infile_name, outfile_name_len);
		outfile_name[outfile_name_len] = 0;
	}

	if (infile_name_len != 0 && infile_name_len == outfile_name_len
	    && strncmp(infile_name, outfile_name, infile_name_len) == 0) {
		log_print(ERROR, "igzip: Error input and output file names must differ\n");
		goto decompress_file_cleanup;
	}

	if (global_options.test == NO_TEST) {
		open_out_file(&out, outfile_name);
		if (out == NULL)
			goto decompress_file_cleanup;
	}

	do {
		if (state.avail_in == 0) {
			state.next_in = inbuf;
			state.avail_in =
			    fread_safe(state.next_in, 1, inbuf_size, in, infile_name);
		}

		state.next_out = outbuf;
		state.avail_out = outbuf_size;

		ret = isal_inflate(&state);
		if (ret != ISAL_DECOMP_OK) {
			log_print(ERROR,
				  "igzip: Error encountered while decompressing file %s\n",
				  infile_name);
			goto decompress_file_cleanup;
		}

		if (out != NULL)
			fwrite_safe(outbuf, 1, state.next_out - outbuf, out, outfile_name);

	} while (!feof(in) || state.avail_out == 0);

	if (state.block_state != ISAL_BLOCK_FINISH)
		log_print(ERROR, "igzip: Error %s does not contain a complete gzip file\n",
			  infile_name);
	else
		success = 1;

      decompress_file_cleanup:
	if (out != NULL && out != stdout) {
		fclose(out);
		if (success)
			set_filetime(outfile_name, file_time);
	}

	if (in != NULL && in != stdin) {
		fclose(in);
		if (success && global_options.remove)
			remove(infile_name);
	}

	if (global_options.outfile_name == NULL && outfile_name != NULL)
		free(outfile_name);

	if (inbuf != NULL)
		free(inbuf);

	if (outbuf != NULL)
		free(outbuf);

	return (success == 0);
}
Example #4
0
static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
{
	connection_struct *conn = fsp->conn;
	int saved_errno = 0;
	int err = 0;
	int err1 = 0;

	remove_pending_lock_requests_by_fid(fsp);

	if (fsp->aio_write_behind) {
		/*
	 	 * If we're finishing write behind on a close we can get a write
		 * error here, we must remember this.
		 */
		int ret = wait_for_aio_completion(fsp);
		if (ret) {
			saved_errno = ret;
			err1 = -1;
		}
	} else {
		cancel_aio_by_fsp(fsp);
	}
 
	/*
	 * If we're flushing on a close we can get a write
	 * error here, we must remember this.
	 */

	if (close_filestruct(fsp) == -1) {
		saved_errno = errno;
		err1 = -1;
	}

	if (fsp->print_file) {
#ifndef AVM_NO_PRINTING
		print_fsp_end(fsp, close_type);
#endif
		file_free(fsp);
		return 0;
	}

	/* If this is an old DOS or FCB open and we have multiple opens on
	   the same handle we only have one share mode. Ensure we only remove
	   the share mode on the last close. */

	if (fsp->fh->ref_count == 1) {
		/* Should we return on error here... ? */
		close_remove_share_mode(fsp, close_type);
	}

	if(fsp->oplock_type) {
		release_file_oplock(fsp);
	}

	locking_close_file(fsp);

	err = fd_close(conn, fsp);

	/* Only save errno if fd_close failed and we don't already
	   have an errno saved from a flush call. */
	if ((err1 != -1) && (err == -1)) {
		saved_errno = errno;
	}

	/* check for magic scripts */
	if (close_type == NORMAL_CLOSE) {
		check_magic(fsp,conn);
	}

	/*
	 * Ensure pending modtime is set after close.
	 */

	if(fsp->pending_modtime && fsp->pending_modtime_owner) {
		set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
	} else if (fsp->last_write_time) {
		set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
	}

	DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
		conn->user,fsp->fsp_name,
		conn->num_files_open,
		(err == -1 || err1 == -1) ? strerror(saved_errno) : ""));

	file_free(fsp);

	if (err == -1 || err1 == -1) {
		errno = saved_errno;
		return saved_errno;
	} else {
		return 0;
	}
}