Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3153374
file.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
file.c
View Options
/******************************************************************************
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "util.h"
#include "bio.h"
#include "fs_bmap.h"
#include "fs_inode.h"
#include "fsck.h"
#include "file.h"
/**
* readi - Read a file
* @ip: The GFS2 Inode
* @buf: The buffer to place result into
* @offset: File offset to begin reading from
* @size: Amount of data to transfer
*
* Returns: The amount of data actually copied or the error
*/
int readi(struct fsck_inode *ip, void *buf, uint64_t offset, unsigned int size)
{
struct fsck_sb *sdp = ip->i_sbd;
struct buffer_head *bh;
uint64_t lblock, dblock=0;
uint32_t extlen = 0;
unsigned int amount;
int not_new = 0;
int journaled = fs_is_jdata(ip);
int copied = 0;
int error = 0;
if (offset >= ip->i_di.di_size){
log_debug("readi: Offset (%"PRIu64") is >= "
"the file size (%"PRIu64").\n",
offset, ip->i_di.di_size);
goto out;
}
if ((offset + size) > ip->i_di.di_size)
size = ip->i_di.di_size - offset;
if (!size){
log_err("readi: Nothing to be read.\n");
goto out;
}
if (journaled){
lblock = offset / sdp->jbsize;
offset %= sdp->jbsize;
}
else{
lblock = offset >> sdp->sb.sb_bsize_shift;
offset &= sdp->sb.sb_bsize - 1;
}
if (fs_is_stuffed(ip))
offset += sizeof(struct gfs2_dinode);
else if (journaled)
offset += sizeof(struct gfs2_meta_header);
while (copied < size){
amount = size - copied;
if (amount > sdp->sb.sb_bsize - offset)
amount = sdp->sb.sb_bsize - offset;
if (!extlen){
error = fs_block_map(ip, lblock, ¬_new, &dblock, &extlen);
if (error){
log_err("readi: The call to fs_block_map() failed.\n");
goto out;
}
}
if (dblock){
error = get_and_read_buf(ip->i_sbd, dblock, &bh, 0);
if (error){
log_err("readi: Unable to perform get_and_read_buf()\n");
goto out;
}
dblock++;
extlen--;
}
else
bh = NULL;
if (bh){
memcpy(buf+copied, BH_DATA(bh)+offset, amount);
relse_buf(ip->i_sbd, bh);
} else {
memset(buf+copied, 0, amount);
}
copied += amount;
lblock++;
offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
}
out:
return (error < 0) ? error : copied;
}
/**
* writei - Write bytes to a file
* @ip: The GFS2 inode
* @buf: The buffer containing information to be written
* @offset: The file offset to start writing at
* @size: The amount of data to write
*
* Returns: The number of bytes correctly written or error code
*/
int writei(struct fsck_inode *ip, void *buf, uint64_t offset, unsigned int size)
{
struct fsck_sb *sdp = ip->i_sbd;
struct buffer_head *dibh, *bh;
uint64_t lblock, dblock;
uint32_t extlen = 0;
unsigned int amount;
int new;
int journaled = fs_is_jdata(ip);
const uint64_t start = offset;
int copied = 0;
int error = 0;
/* Bomb out on writing nothing.
Posix says we can't change the time here. */
if (!size)
goto fail; /* Not really an error */
if (fs_is_stuffed(ip) &&
((start + size) > (sdp->sb.sb_bsize - sizeof(struct gfs2_dinode)))){
error = fs_unstuff_dinode(ip);
if (error)
goto fail;
}
if (journaled){
lblock = offset / sdp->jbsize;
offset %= sdp->jbsize;
}
else{
lblock = offset >> sdp->sb.sb_bsize_shift;
offset &= sdp->sb.sb_bsize - 1;
}
if (fs_is_stuffed(ip))
offset += sizeof(struct gfs2_dinode);
else if (journaled)
offset += sizeof(struct gfs2_meta_header);
while (copied < size){
amount = size - copied;
if (amount > sdp->sb.sb_bsize - offset)
amount = sdp->sb.sb_bsize - offset;
if (!extlen){
new = 1;
error = fs_block_map(ip, lblock, &new, &dblock, &extlen);
if (error)
goto fail;
if(!dblock){
log_crit("fs_writei: "
"Unable to map logical block to real block.\n");
log_crit("Uncircumventable error.\n");
exit(EXIT_FAILURE);
}
}
error = get_and_read_buf(ip->i_sbd, dblock, &bh, 0);
if (error)
goto fail;
if(journaled && dblock != ip->i_di.di_num.no_addr ) {
set_meta(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
}
memcpy(BH_DATA(bh)+offset, buf+copied, amount);
write_buf(ip->i_sbd, bh, 0);
relse_buf(ip->i_sbd, bh);
copied += amount;
lblock++;
dblock++;
extlen--;
offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
}
out:
error = get_and_read_buf(ip->i_sbd, ip->i_num.no_addr, &dibh, 0);
if (error){
log_err("fs_writei: "
"Unable to get inode buffer.\n");
return -1;
}
error = check_meta(dibh, GFS2_METATYPE_DI);
if(error){
log_err("fs_writei: "
"Buffer is not a valid inode.\n");
relse_buf(ip->i_sbd, dibh);
return -1;
}
if (ip->i_di.di_size < start + copied)
ip->i_di.di_size = start + copied;
ip->i_di.di_mtime = ip->i_di.di_ctime = time(NULL);
gfs2_dinode_out(&ip->i_di, BH_DATA(dibh));
write_buf(ip->i_sbd, dibh, 0);
relse_buf(ip->i_sbd, dibh);
return copied;
fail:
if (copied)
goto out;
return error;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Feb 25, 5:49 PM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464914
Default Alt Text
file.c (5 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment