C - Writing multi-lined txt in memory - malloc

I'm working in PUTTY, using C. I have a .txt file with the data of multiple users. For example, a line looks like: "SSNumber, Name, PhoneNumber, Class, Age(...)". There's only one line per user. I want to write it in a shared memory location with malloc. But I'll have to change one of the fields later on. How can I do this? Do I need to read it line by line, anyway? It's very confusing.
Thanks!
Is this enough?
if (fp != NULL) {
/* Vai ao fim do ficheiro. */
if (fseek(fp, 0L, SEEK_END) == 0) {
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
source = malloc(sizeof(char) * (bufsize + 1));
if (fseek(fp, 0L, SEEK_SET) == 0) { /* Error */ }
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if (newLen == 0) {
fputs("Error reading file", stderr);
} else {
source[++newLen] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}

Related

RECOVER Pset_4 CS50 - Images recovered are incomplete

So I'm doing the CS50 pset4 recover task (where you need to search for jpg files on a memory card and whenever you find one- you open a new file and write the jpg found to the new file). I have written the code in a slightly different manner then what is told in the course but I think(hope) my logic is right. I am able to recover all 50 images but the images are incomplete and distorted. Also for some reason the 050th image is not opening. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE; //defining a byte = 8 bits or 8 0's or 1's
int main(int argc, char *argv[]) {
//assigning variables
int BLOCK_SIZE = 512;
BYTE buffer[BLOCK_SIZE];
int i = 0;
char* nf = malloc(sizeof(int)*3);
//checking to see a file name is given
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
//opening said file
FILE *rfile = fopen(argv[1], "r");
if(rfile == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//opening a copy
FILE *c = fopen(argv[1], "r");
if(c == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//checking 512 bytes again and again for orginal
while (fread (buffer, 1, BLOCK_SIZE, rfile) == BLOCK_SIZE)
{
fseek(c, ftell(rfile) , SEEK_SET); //fread (buffer, 1, BLOCK_SIZE, c);
sprintf(nf, "%03i.jpg", i); //000, 001, 002
//opening a file to write in
FILE *img = fopen(nf, "w");
if(img == NULL)
{
return 1;
}
//Is it a jpeg!?
if (buffer[0]==0xff && buffer[1]==0xd8 && buffer[2]==0xff && (buffer[3] & 0xf0) == 0xe0)
{
//writing the img in a file called img
fwrite(buffer, 512, 1, img);
fwrite(c, BLOCK_SIZE, 2048, img);
i++; //making sure a new file is opened next time
}
fclose(img);
}
fclose(c);
fclose(rfile);
free(nf); }

CS50 Recover runs and recovers all files except the first one

My question is regarding the Recover assignment as part of CS50.
The code is running (finally) and it produces 50 JPEG files, and most of them are the correct images, except the first file is not an image, therefore it doesn't pass check50.
I have spent a long time trying to figure out what the problem is but I cannot pinpoint it so I am hoping someone might be able to help me out so I can move on.
Thanks in advance! Here is my code:
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Usage: Name of Memory Card File\n");
return 1;
}
char *readfile = argv[1];
// open memory card file
FILE *card_ptr = fopen(readfile, "r");
if (card_ptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", readfile);
return 2;
}
//Declare a buffer to read into
unsigned char *buffer = malloc(512);
//to check if we have already found a file
bool (jpgAlreadyNew) = false;
//declare counter for the number of files found and a file pointer
int filenumber = 0;
FILE *new_jpg_ptr = NULL;
char filename[8];
//read in bytes until reach EOF
while (fread(buffer, 1, 512, card_ptr) != 0x00)
{
//if we reach the header pattern of bytes
if (buffer [0] == 0xff && buffer [1] == 0xd8 && buffer [2] == 0xff && (buffer [3] & 0xf0) == 0xe0)
{
//if there is not already a JPEG file found
if (!jpgAlreadyNew)
{
//change the bool value
(jpgAlreadyNew) = true;
//open new file
sprintf(filename, "%03i.jpg", filenumber);
new_jpg_ptr = fopen(filename, "w");
if (new_jpg_ptr == NULL)
{
return 3;
}
//add to counter of files found
filenumber++;
//write files from buffer into new img file
fwrite(buffer, 1, 512, new_jpg_ptr);
}
//if there is already a JPEG file found
if (jpgAlreadyNew)
{
//close the previous file which would now be complete
fclose(new_jpg_ptr);
//open new file
sprintf(filename, "%03i.jpg", filenumber);
new_jpg_ptr = fopen(filename, "w");
if (new_jpg_ptr == NULL)
{
return 4;
}
//add to counter of files found
filenumber++;
//write files from buffer into new img file
fwrite(buffer, 1, 512, new_jpg_ptr);
}
}
// else if we do not see pattern of header bytes
else
{
//if already found a jpg file which is open then write the bytes to that file
if (jpgAlreadyNew)
{
fwrite(buffer, 1, 512, new_jpg_ptr);
}
//if no file found yet, discard and move on
if (!jpgAlreadyNew)
{
continue;
}
}
}
//free memory
free (buffer);
//close pointers and end program successfully
fclose(card_ptr);
fclose(new_jpg_ptr);
return 0;
}
Let's walk through the program starting with finding the first jpeg signature:
This if (!jpgAlreadyNew) evaluates to true, so it enters the if block; the first thing it does is (jpgAlreadyNew) = true;. When it is done creating the file and writing the first block, what happens next? This if (jpgAlreadyNew). Which also evaluates to true. So it closes 000.jpg and moves along.
Since jpgAlreadyNew is a boolean, an if {} else {} construct would suffice.

linux kernel module data compression

linux 2.6
I am writing a LKM. I need to compress and decompress on the fly many different chunks of text.
I prefer to call kernel api, avoiding to include and compile external libraries.
Are there kernel Api to compress and decompress memory ?
source and destination buffers can be both in kernel memory or one in kernel the other in user space.
Not sure why kernel.org excludes the compression part.
One may need to mimic from its official skcipher example, in which the procedure is like below:
tfm = crypto_alloc_tfm("yourAlg",
CRYPTO_TFM_MODE_yourAlg);
req = skcipher_request_alloc(tfm, GFP_KERNEL);
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
test_tfm_cb,
result);
crypto_cipher_setkey(tfm, key, keylength);
crypto_cipher_encrypt(tfm, &scatterlist,
numlists);
tfm_request_free(req);
crypto_free_tfm(tfm);
Notice kernel now is moving to async, however callback is not shown in latest header file.
/**
* acomp_request_set_callback() -- Sets an asynchronous callback
*
* Callback will be called when an asynchronous operation on a given
* request is finished.
*
* #req: request that the callback will be set for
* #flgs: specify for instance if the operation may backlog
* #cmlp: callback which will be called
* #data: private data used by the caller
*/
static inline void acomp_request_set_callback(struct acomp_req *req,
u32 flgs,
crypto_completion_t cmpl,
void *data)
{
req->base.complete = cmpl;
req->base.data = data;
req->base.flags = flgs;
}
Example code:
struct comp_testvec tv, int mode;
int ilen = tv.inlen;
char *str_input = tv.input;
int olen = tv.outlen;
char *str_output = tv.output;
struct scatterlist sg[2];
struct scatterlist sg2[2];
char *input;
char *output;
char *input2;
char *output2;
struct acomp_req *req;
struct crypto_acomp *tfm;
struct tcrypt_result result;
int ret = 0;
input = kmalloc(ilen, GFP_KERNEL);
output = kmalloc(olen, GFP_KERNEL);
input2 = kmalloc(olen, GFP_KERNEL);
output2 = kmalloc(ilen, GFP_KERNEL);
char *driver = tv.alg;
tfm = crypto_alloc_acomp(driver, CRYPTO_ALG_TYPE_ACOMPRESS,
CRYPTO_ALG_TYPE_ACOMPRESS_MASK);
if (IS_ERR(tfm)) {
printk(KERN_ERR "alg: acomp: Failed to load transform for "
"%s: %ld\n", driver, PTR_ERR(tfm));
return PTR_ERR(tfm);
}
init_completion(&result.completion);
if (mode == 0)
{
//zip
memcpy(input,str_input,ilen);
printk("input => %s\n", input);
print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, input, ilen, false);
printk("alg => %s\n",driver);
sg_init_one(&sg[0], input, ilen);
sg_init_one(&sg[1], output, COMP_BUF_SIZE);
req = acomp_request_alloc(tfm);
if(!req)
{
printk("error req = null\n");
crypto_free_acomp(tfm);
return -1;
}
acomp_request_set_params(req, &sg[0], &sg[1], ilen, COMP_BUF_SIZE);
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);
ret = crypto_acomp_compress(req);
if(ret == -EINPROGRESS || ret == -EBUSY)
{
ret = wait_for_completion_interruptible(
&result.completion);
if (!ret && !((ret = result.err)))
{
reinit_completion(&result.completion);
}
}
else if(ret == 0)
{
printk("succ\n");
}
else
{
printk("error ret = %d\n",ret);
goto out;
}
printk("compress => \n");
print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, output, olen, false);
} else if (mode == 1) {
//unzip
memcpy(input2,str_output,olen);
printk("input => \n");
print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, input2, olen, false);
char *driver = tv.alg;
printk("alg => %s\n",driver);
//sg init
sg_init_one(&sg2[0], input2, ilen);
sg_init_one(&sg2[1], output2, COMP_BUF_SIZE);
req = acomp_request_alloc(tfm);
if(!req)
{
printk("error req = null\n");
crypto_free_acomp(tfm);
return -1;
}
acomp_request_set_params(req, &sg2[0], &sg2[1], ilen, COMP_BUF_SIZE);
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);
ret = crypto_acomp_decompress(req);
if(ret == -EINPROGRESS || ret == -EBUSY)
{
ret = wait_for_completion_interruptible(
&result.completion);
if (!ret && !((ret = result.err)))
{
reinit_completion(&result.completion);
}
}
else if(ret == 0)
{
printk("succ\n");
}
else
{
printk("error ret = %d\n",ret);
goto out;
}
printk("decompress => %s\n", output2);
print_hex_dump(KERN_CONT, "| ", DUMP_PREFIX_OFFSET, 16, 1, output2, ilen, false);

Chibios and the SIM900 Shiled

i have this problem,
i have STM32 Nucleo L152RE and a Shield SIM 900,
now if i write this easy thread all work well,
'static THD_WORKING_AREA(waRead, 128);
static THD_FUNCTION(Thread,arg) {
(void)arg;
chRegSetThreadName("th_callback");
while (TRUE){
/* This will wait for a character to be received */
uint8_t c = sdGet(&SD1); //questo prende il carattere
sdPut(&SD2, c); // questo lo spara alla terminale
}
}
'
when i sand a AT commnad i see the ok answer.
Now i create this buffer
'static uint8_t bufferMsg[128];'
and i use this thread for store the answer
' static THD_WORKING_AREA(waRead5, 128);
static THD_FUNCTION(Thread5,arg) {
chRegSetThreadName("th_Riempio_Buffer");
msg_t charbuf;
int count=0;
uint8_t c;
event_listener_t Uart1Data;
eventmask_t flags;
chEvtRegisterMask((event_source_t *)chnGetEventSource(&SD1), &Uart1Data, EVENT_MASK(1));
while (TRUE) {
chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));
chSysLock();
flags =chEvtGetAndClearFlags(&Uart1Data);
chSysUnlock();
if (flags & CHN_INPUT_AVAILABLE)
{
do
{
charbuf = chnGetTimeout(&SD1,TIME_IMMEDIATE);
if (charbuf != Q_TIMEOUT)
{
while((charbuf != '\n') && (count < 128)) {
sdWrite(&SD2, (uint8_t *)B3,4); // va bene
bufferMsg[count]= charbuf;
count++;
}
}
}
while (charbuf != Q_TIMEOUT);
}
}
}
'
this threads don't work and don't store the answer, can you help me?
best regards
A.
fot me i use,
Define
#define buffer_size 128
char buffer[buffer_size + 1];
int nbytes = 0;
Function
void SIM_callback(){ /* GSM900 Serial */
char x = SIM.getc();
buffer[nbytes] = x;
nbytes++; if (nbytes > buffer_size) nbytes = buffer_size;
buffer[nbytes] = '\0';
}
Main
main (){
// Clear Buffer
buffer[nbytes] = '\0';
...
while(1);
...
}

Filesystem has been set read-only for clusters badly computed error

my sd cart run a long time in embed linux system,but sometime the filesystem set readonly and print bellow msg:
clusters badly computed (587 != 531)
FAT: Filesystem panic (dev hda6)
i see source code from linux kernel as show this: who can explain why this error,tks very much.
/*
* fat_chain_add() adds a new cluster to the chain of clusters represented
* by inode.
*/
int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
{
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
int ret, new_fclus, last;
/*
* We must locate the last cluster of the file to add this new
* one (new_dclus) to the end of the link list (the FAT).
*/
last = new_fclus = 0;
if (MSDOS_I(inode)->i_start) {
int fclus, dclus;
ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
if (ret < 0)
return ret;
new_fclus = fclus + 1;
last = dclus;
}
/* add new one to the last of the cluster chain */
if (last) {
struct fat_entry fatent;
fatent_init(&fatent);
ret = fat_ent_read(inode, &fatent, last);
if (ret >= 0) {
int wait = inode_needs_sync(inode);
ret = fat_ent_write(inode, &fatent, new_dclus, wait);
fatent_brelse(&fatent);
}
if (ret < 0)
return ret;
/*
* FIXME:Although we can add this cache, fat_cache_add() is
* assuming to be called after linear search with fat_cache_id.
*/
// fat_cache_add(inode, new_fclus, new_dclus);
} else {
MSDOS_I(inode)->i_start = new_dclus;
MSDOS_I(inode)->i_logstart = new_dclus;
/*
* Since generic_write_sync() synchronizes regular files later,
* we sync here only directories.
*/
if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) {
ret = fat_sync_inode(inode);
if (ret)
return ret;
} else
mark_inode_dirty(inode);
}
if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
fat_fs_error(sb, "clusters badly computed (%d != %llu)",
new_fclus,
(llu)(inode->i_blocks >> (sbi->cluster_bits - 9)));
fat_cache_inval_inode(inode);
}
inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
return 0;
}

Resources