Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cs503zchen
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Ziheng Chen
cs503zchen
Commits
68445955
Commit
68445955
authored
5 months ago
by
Ziheng Chen
Browse files
Options
Downloads
Patches
Plain Diff
Upload New File
parent
ffe858d1
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
w4hw/codes/sdbsc.c
+787
-0
787 additions, 0 deletions
w4hw/codes/sdbsc.c
with
787 additions
and
0 deletions
w4hw/codes/sdbsc.c
0 → 100644
+
787
−
0
View file @
68445955
#include
<stdio.h>
#include
<stdlib.h>
#include
<fcntl.h>
//c library for system call file routines
#include
<string.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
<stdbool.h>
// database include files
#include
"db.h"
#include
"sdbsc.h"
/*
* open_db
* dbFile: name of the database file
* should_truncate: indicates if opening the file also empties it
*
* returns: File descriptor on success, or ERR_DB_FILE on failure
*
* console: Does not produce any console I/O on success
* M_ERR_DB_OPEN on error
*
*/
int
open_db
(
char
*
dbFile
,
bool
should_truncate
)
{
// Set permissions: rw-rw----
// see sys/stat.h for constants
mode_t
mode
=
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
;
// open the file if it exists for Read and Write,
// create it if it does not exist
int
flags
=
O_RDWR
|
O_CREAT
;
if
(
should_truncate
)
flags
+=
O_TRUNC
;
// Now open file
int
fd
=
open
(
dbFile
,
flags
,
mode
);
if
(
fd
==
-
1
)
{
// Handle the error
printf
(
M_ERR_DB_OPEN
);
return
ERR_DB_FILE
;
}
return
fd
;
}
/*
* get_student
* fd: linux file descriptor
* id: the student id we are looking forname of the
* *s: a pointer where the located (if found) student data will be
* copied
*
* returns: NO_ERROR student located and copied into *s
* ERR_DB_FILE database file I/O issue
* SRCH_NOT_FOUND student was not located in the database
*
* console: Does not produce any console I/O used by other functions
*/
int
get_student
(
int
fd
,
int
id
,
student_t
*
s
)
{
// TODO
// Validate the ID range
if
(
id
<
MIN_STD_ID
||
id
>
MAX_STD_ID
)
{
return
SRCH_NOT_FOUND
;
}
// Calculate the offset
off_t
offset
=
id
*
STUDENT_RECORD_SIZE
;
// Move the file pointer to the correct student record
if
(
lseek
(
fd
,
offset
,
SEEK_SET
)
<
0
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Read the student record from file
if
(
read
(
fd
,
s
,
STUDENT_RECORD_SIZE
)
!=
STUDENT_RECORD_SIZE
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Check if the student record is empty (deleted)
if
(
s
->
id
==
DELETED_STUDENT_ID
)
{
return
SRCH_NOT_FOUND
;
}
// Student found, return success
return
NO_ERROR
;
//return NOT_IMPLEMENTED_YET;
}
/*
* add_student
* fd: linux file descriptor
* id: student id (range is defined in db.h )
* fname: student first name
* lname: student last name
* gpa: GPA as an integer (range defined in db.h)
*
* Adds a new student to the database. After calculating the index for the
* student, check if there is another student already at that location. A good
* way is to use something like memcmp() to ensure that the location for this
* student contains all zero byes indicating the space is empty.
*
* returns: NO_ERROR student added to database
* ERR_DB_FILE database file I/O issue
* ERR_DB_OP database operation logically failed (aka student
* already exists)
*
*
* console: M_STD_ADDED on success
* M_ERR_DB_ADD_DUP student already exists
* M_ERR_DB_READ error reading or seeking the database file
* M_ERR_DB_WRITE error writing to db file (adding student)
*
*/
int
add_student
(
int
fd
,
int
id
,
char
*
fname
,
char
*
lname
,
int
gpa
)
{
// TODO
student_t
student
=
{
0
};
// Empty struct to check existing record
off_t
offset
=
id
*
STUDENT_RECORD_SIZE
;
// 🔹 Validate ID and GPA Range
if
(
validate_range
(
id
,
gpa
)
!=
NO_ERROR
)
{
printf
(
M_ERR_STD_RNG
);
return
ERR_DB_OP
;
}
// 🔹 Move to correct position
if
(
lseek
(
fd
,
offset
,
SEEK_SET
)
<
0
)
{
perror
(
"Error seeking in database file"
);
return
ERR_DB_FILE
;
}
// 🔹 Read existing student record
ssize_t
bytes_read
=
read
(
fd
,
&
student
,
STUDENT_RECORD_SIZE
);
if
(
bytes_read
<
0
)
{
perror
(
"Error reading database file"
);
return
ERR_DB_FILE
;
}
// 🔹 If student already exists, return error
if
(
memcmp
(
&
student
,
&
EMPTY_STUDENT_RECORD
,
STUDENT_RECORD_SIZE
)
!=
0
)
{
printf
(
M_ERR_DB_ADD_DUP
,
id
);
return
ERR_DB_OP
;
}
// 🔹 Fill new student details
student
.
id
=
id
;
student
.
gpa
=
gpa
;
strncpy
(
student
.
fname
,
fname
,
sizeof
(
student
.
fname
)
-
1
);
strncpy
(
student
.
lname
,
lname
,
sizeof
(
student
.
lname
)
-
1
);
// 🔹 Move back before writing
if
(
lseek
(
fd
,
offset
,
SEEK_SET
)
<
0
)
{
perror
(
"Error seeking in database file before writing"
);
return
ERR_DB_FILE
;
}
// 🔹 Write student record
ssize_t
bytes_written
=
write
(
fd
,
&
student
,
STUDENT_RECORD_SIZE
);
if
(
bytes_written
!=
STUDENT_RECORD_SIZE
)
{
perror
(
"Error writing student record to database"
);
return
ERR_DB_FILE
;
}
printf
(
M_STD_ADDED
,
id
);
return
NO_ERROR
;
//printf(M_NOT_IMPL);
//return NOT_IMPLEMENTED_YET;
}
/*
* del_student
* fd: linux file descriptor
* id: student id to be deleted
*
* Removes a student to the database. Use the get_student() function to
* locate the student to be deleted. If there is a student at that location
* write an empty student record - see EMPTY_STUDENT_RECORD from db.h at
* that location.
*
* returns: NO_ERROR student deleted from database
* ERR_DB_FILE database file I/O issue
* ERR_DB_OP database operation logically failed (aka student
* not in database)
*
*
* console: M_STD_DEL_MSG on success
* M_STD_NOT_FND_MSG student not in database, cant be deleted
* M_ERR_DB_READ error reading or seeking the database file
* M_ERR_DB_WRITE error writing to db file (adding student)
*
*/
int
del_student
(
int
fd
,
int
id
)
{
// TODO
// Validate ID range
if
(
id
<
MIN_STD_ID
||
id
>
MAX_STD_ID
)
{
printf
(
M_STD_NOT_FND_MSG
,
id
);
return
ERR_DB_OP
;
}
// Check if the student exists
student_t
student
;
int
result
=
get_student
(
fd
,
id
,
&
student
);
if
(
result
==
SRCH_NOT_FOUND
)
{
printf
(
M_STD_NOT_FND_MSG
,
id
);
return
ERR_DB_OP
;
}
if
(
result
==
ERR_DB_FILE
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Calculate the offset of the student record
off_t
offset
=
id
*
STUDENT_RECORD_SIZE
;
// Move to the correct position
if
(
lseek
(
fd
,
offset
,
SEEK_SET
)
<
0
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Write EMPTY_STUDENT_RECORD to mark the student as deleted
if
(
write
(
fd
,
&
EMPTY_STUDENT_RECORD
,
STUDENT_RECORD_SIZE
)
!=
STUDENT_RECORD_SIZE
)
{
printf
(
M_ERR_DB_WRITE
);
return
ERR_DB_FILE
;
}
// Success: Student deleted
printf
(
M_STD_DEL_MSG
,
id
);
return
NO_ERROR
;
//printf(M_NOT_IMPL);
//return NOT_IMPLEMENTED_YET;
}
/*
* count_db_records
* fd: linux file descriptor
*
* Counts the number of records in the database. Start by reading the
* database at the beginning, and continue reading individual records
* until you it EOF. EOF is when the read() syscall returns 0. Check
* if a slot is empty or previously deleted by investigating if all of
* the bytes in the record read are zeros - I would suggest using memory
* compare memcmp() for this. Create a counter variable and initialize it
* to zero, every time a non-zero record is read increment the counter.
*
* returns: <number> returns the number of records in db on success
* ERR_DB_FILE database file I/O issue
* ERR_DB_OP database operation logically failed (aka student
* not in database)
*
*
* console: M_DB_RECORD_CNT on success, to report the number of students in db
* M_DB_EMPTY on success if the record count in db is zero
* M_ERR_DB_READ error reading or seeking the database file
* M_ERR_DB_WRITE error writing to db file (adding student)
*
*/
int
count_db_records
(
int
fd
)
{
// TODO
student_t
student
;
int
record_count
=
0
;
// Move to the start of the database
if
(
lseek
(
fd
,
0
,
SEEK_SET
)
<
0
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Read and count valid records
// Read and count valid records
ssize_t
bytes_read
;
while
((
bytes_read
=
read
(
fd
,
&
student
,
STUDENT_RECORD_SIZE
))
==
STUDENT_RECORD_SIZE
)
{
if
(
memcmp
(
&
student
,
&
EMPTY_STUDENT_RECORD
,
STUDENT_RECORD_SIZE
)
!=
0
)
{
record_count
++
;
// Increment only if the record is non-empty
}
}
// Check for errors during read
if
(
bytes_read
<
0
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Print appropriate message
if
(
record_count
==
0
)
{
printf
(
M_DB_EMPTY
);
}
else
{
printf
(
M_DB_RECORD_CNT
,
record_count
);
}
return
record_count
;
//printf(M_NOT_IMPL);
//return NOT_IMPLEMENTED_YET;
}
/*
* print_db
* fd: linux file descriptor
*
* Prints all records in the database. Start by reading the
* database at the beginning, and continue reading individual records
* until you it EOF. EOF is when the read() syscall returns 0. Check
* if a slot is empty or previously deleted by investigating if all of
* the bytes in the record read are zeros - I would suggest using memory
* compare memcmp() for this. Be careful as the database might be empty.
* on the first real row encountered print the header for the required output:
*
* printf(STUDENT_PRINT_HDR_STRING, "ID",
* "FIRST_NAME", "LAST_NAME", "GPA");
*
* then for each valid record encountered print the required output:
*
* printf(STUDENT_PRINT_FMT_STRING, student.id, student.fname,
* student.lname, calculated_gpa_from_student);
*
* The code above assumes you are reading student records into a local
* variable named student that is of type student_t. Also dont forget that
* the GPA in the student structure is an int, to convert it into a real
* gpa divide by 100.0 and store in a float variable.
*
* returns: NO_ERROR on success
* ERR_DB_FILE database file I/O issue
*
*
* console: <see above> on success, print table or database empty
* M_ERR_DB_READ error reading or seeking the database file
*
*/
int
print_db
(
int
fd
)
{
// TODO
student_t
student
;
int
record_count
=
0
;
bool
printed_header
=
false
;
// Flag to print header only once
// Move to the start of the database
if
(
lseek
(
fd
,
0
,
SEEK_SET
)
<
0
)
{
printf
(
M_ERR_DB_READ
);
return
ERR_DB_FILE
;
}
// Read and print valid records
while
(
read
(
fd
,
&
student
,
STUDENT_RECORD_SIZE
)
==
STUDENT_RECORD_SIZE
)
{
if
(
memcmp
(
&
student
,
&
EMPTY_STUDENT_RECORD
,
STUDENT_RECORD_SIZE
)
!=
0
)
{
// Print header only once
if
(
!
printed_header
)
{
printf
(
STUDENT_PRINT_HDR_STRING
,
"ID"
,
"FIRST_NAME"
,
"LAST_NAME"
,
"GPA"
);
printed_header
=
true
;
}
// Calculate GPA as float
float
real_gpa
=
student
.
gpa
/
100
.
0
;
// Print student record
printf
(
STUDENT_PRINT_FMT_STRING
,
student
.
id
,
student
.
fname
,
student
.
lname
,
real_gpa
);
record_count
++
;
}
}
// Handle database being empty
if
(
record_count
==
0
)
{
printf
(
M_DB_EMPTY
);
}
return
NO_ERROR
;
//printf(M_NOT_IMPL);
//return NOT_IMPLEMENTED_YET;
}
/*
* print_student
* *s: a pointer to a student_t structure that should
* contain a valid student to be printed
*
* Start by ensuring that provided student pointer is valid. To do this
* make sure it is not NULL and that s->id is not zero. After ensuring
* that the student is valid, print it the exact way that is described
* in the print_db() function by first printing the header then the
* student data:
*
* printf(STUDENT_PRINT_HDR_STRING, "ID",
* "FIRST NAME", "LAST_NAME", "GPA");
*
* printf(STUDENT_PRINT_FMT_STRING, s->id, s->fname,
* student.lname, calculated_gpa_from_s);
*
* Dont forget that the GPA in the student structure is an int, to convert
* it into a real gpa divide by 100.0 and store in a float variable.
*
* returns: nothing, this is a void function
*
*
* console: <see above> on success, print table or database empty
* M_ERR_STD_PRINT if the function argument s is NULL or if
* s->id is zero
*
*/
void
print_student
(
student_t
*
s
)
{
// TODO
// Validate student pointer
if
(
s
==
NULL
||
s
->
id
==
0
)
{
printf
(
M_ERR_STD_PRINT
);
return
;
}
// Print header
printf
(
STUDENT_PRINT_HDR_STRING
,
"ID"
,
"FIRST NAME"
,
"LAST NAME"
,
"GPA"
);
// Calculate real GPA
float
real_gpa
=
s
->
gpa
/
100
.
0
;
// Print student details
printf
(
STUDENT_PRINT_FMT_STRING
,
s
->
id
,
s
->
fname
,
s
->
lname
,
real_gpa
);
//printf(M_NOT_IMPL);
}
/*
* NOTE IMPLEMENTING THIS FUNCTION IS EXTRA CREDIT
*
* compress_db
* fd: linux file descriptor
*
* This assignment takes advantage of the way Linux handles sparse files
* on disk. Thus if there is a large hole between student records, Linux
* will not use any physical storage. However, when a database record is
* deleted storage is used to write a blank - see EMPTY_STUDENT_RECORD from
* db.h - record.
*
* Since Linux provides no way to delete data in the middle of a file, and
* deleted records take up physical storage, this function will compress the
* database by rewriting a new database file that only includes valid student
* records. There are a number of ways to do this, but since this is extra credit
* you need to figure this out on your own.
*
* At a high level create a temporary database file then copy all valid students from
* the active database (passed in via fd) to the temporary file. When this is done
* rename the temporary database file to the name of the real database file. See
* the constants in db.h for required file names:
*
* #define DB_FILE "student.db" //name of database file
* #define TMP_DB_FILE ".tmp_student.db" //for extra credit
*
* Note that you are passed in the fd of the database file to be compressed,
* it is very likely you will need to close it to overwrite it with the
* compressed version of the file. To ensure the caller can work with the
* compressed file after you create it, it is a good design to return the fd
* of the new compressed file from this function
*
* returns: <number> returns the fd of the compressed database file
* ERR_DB_FILE database file I/O issue
*
*
* console: M_DB_COMPRESSED_OK on success, the db was successfully compressed.
* M_ERR_DB_OPEN error when opening/creating temporary database file.
* this error should also be returned after you
* compressed the database file and if you are unable
* to open it to pass the fd back to the caller
* M_ERR_DB_CREATE error creating the db file. For instance the
* inability to copy the temporary file back as
* the primary database file.
* M_ERR_DB_READ error reading or seeking the the db or tempdb file
* M_ERR_DB_WRITE error writing to db or tempdb file (adding student)
*
*/
int
compress_db
(
int
fd
)
{
// TODO
student_t
student
;
// Open a temporary database file
int
tmp_fd
=
open
(
TMP_DB_FILE
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
);
if
(
tmp_fd
<
0
)
{
printf
(
M_ERR_DB_OPEN
);
return
ERR_DB_FILE
;
}
// Move to the start of the current database
if
(
lseek
(
fd
,
0
,
SEEK_SET
)
<
0
)
{
printf
(
M_ERR_DB_READ
);
close
(
tmp_fd
);
return
ERR_DB_FILE
;
}
// Read and copy valid records
while
(
read
(
fd
,
&
student
,
STUDENT_RECORD_SIZE
)
==
STUDENT_RECORD_SIZE
)
{
if
(
memcmp
(
&
student
,
&
EMPTY_STUDENT_RECORD
,
STUDENT_RECORD_SIZE
)
!=
0
)
{
// Write valid student to the new database
if
(
write
(
tmp_fd
,
&
student
,
STUDENT_RECORD_SIZE
)
!=
STUDENT_RECORD_SIZE
)
{
printf
(
M_ERR_DB_WRITE
);
close
(
tmp_fd
);
return
ERR_DB_FILE
;
}
}
}
// Close both files
close
(
fd
);
close
(
tmp_fd
);
// Replace old database file with the new compressed one
if
(
rename
(
TMP_DB_FILE
,
DB_FILE
)
<
0
)
{
printf
(
M_ERR_DB_CREATE
);
return
ERR_DB_FILE
;
}
// Reopen the new compressed database
int
new_fd
=
open
(
DB_FILE
,
O_RDWR
);
if
(
new_fd
<
0
)
{
printf
(
M_ERR_DB_OPEN
);
return
ERR_DB_FILE
;
}
// Compression successful
printf
(
M_DB_COMPRESSED_OK
);
return
new_fd
;
//printf(M_NOT_IMPL);
//return fd;
}
/*
* validate_range
* id: proposed student id
* gpa: proposed gpa
*
* This function validates that the id and gpa are in the allowable ranges
* as per the specifications. It checks if the values are within the
* inclusive range using constents in db.h
*
* returns: NO_ERROR on success, both ID and GPA are in range
* EXIT_FAIL_ARGS if either ID or GPA is out of range
*
* console: This function does not produce any output
*
*/
int
validate_range
(
int
id
,
int
gpa
)
{
if
((
id
<
MIN_STD_ID
)
||
(
id
>
MAX_STD_ID
))
return
EXIT_FAIL_ARGS
;
if
((
gpa
<
MIN_STD_GPA
)
||
(
gpa
>
MAX_STD_GPA
))
return
EXIT_FAIL_ARGS
;
return
NO_ERROR
;
}
/*
* usage
* exename: the name of the executable from argv[0]
*
* Prints this programs expected usage
*
* returns: nothing, this is a void function
*
* console: This function prints the usage information
*
*/
void
usage
(
char
*
exename
)
{
printf
(
"usage: %s -[h|a|c|d|f|p|z] options. Where:
\n
"
,
exename
);
printf
(
"
\t
-h: prints help
\n
"
);
printf
(
"
\t
-a id first_name last_name gpa(as 3 digit int): adds a student
\n
"
);
printf
(
"
\t
-c: counts the records in the database
\n
"
);
printf
(
"
\t
-d id: deletes a student
\n
"
);
printf
(
"
\t
-f id: finds and prints a student in the database
\n
"
);
printf
(
"
\t
-p: prints all records in the student database
\n
"
);
printf
(
"
\t
-x: compress the database file [EXTRA CREDIT]
\n
"
);
printf
(
"
\t
-z: zero db file (remove all records)
\n
"
);
}
// Welcome to main()
int
main
(
int
argc
,
char
*
argv
[])
{
char
opt
;
// user selected option
int
fd
;
// file descriptor of database files
int
rc
;
// return code from various operations
int
exit_code
;
// exit code to shell
int
id
;
// userid from argv[2]
int
gpa
;
// gpa from argv[5]
// space for a student structure which we will get back from
// some of the functions we will be writing such as get_student(),
// and print_student().
student_t
student
=
{
0
};
// This function must have at least one arg, and the arg must start
// with a dash
if
((
argc
<
2
)
||
(
*
argv
[
1
]
!=
'-'
))
{
usage
(
argv
[
0
]);
exit
(
1
);
}
// The option is the first character after the dash for example
//-h -a -c -d -f -p -x -z
opt
=
(
char
)
*
(
argv
[
1
]
+
1
);
// get the option flag
// handle the help flag and then exit normally
if
(
opt
==
'h'
)
{
usage
(
argv
[
0
]);
exit
(
EXIT_OK
);
}
// now lets open the file and continue if there is no error
// note we are not truncating the file using the second
// parameter
fd
=
open_db
(
DB_FILE
,
false
);
if
(
fd
<
0
)
{
exit
(
EXIT_FAIL_DB
);
}
// set rc to the return code of the operation to ensure the program
// use that to determine the proper exit_code. Look at the header
// sdbsc.h for expected values.
exit_code
=
EXIT_OK
;
switch
(
opt
)
{
case
'a'
:
// arv[0] arv[1] arv[2] arv[3] arv[4] arv[5]
// prog_name -a id first_name last_name gpa
//-------------------------------------------------------
// example: prog_name -a 1 John Doe 341
if
(
argc
!=
6
)
{
usage
(
argv
[
0
]);
exit_code
=
EXIT_FAIL_ARGS
;
break
;
}
// convert id and gpa to ints from argv. For this assignment assume
// they are valid numbers
id
=
atoi
(
argv
[
2
]);
gpa
=
atoi
(
argv
[
5
]);
exit_code
=
validate_range
(
id
,
gpa
);
if
(
exit_code
==
EXIT_FAIL_ARGS
)
{
printf
(
M_ERR_STD_RNG
);
break
;
}
rc
=
add_student
(
fd
,
id
,
argv
[
3
],
argv
[
4
],
gpa
);
if
(
rc
<
0
)
exit_code
=
EXIT_FAIL_DB
;
break
;
case
'c'
:
// arv[0] arv[1]
// prog_name -c
//-----------------
// example: prog_name -c
rc
=
count_db_records
(
fd
);
if
(
rc
<
0
)
exit_code
=
EXIT_FAIL_DB
;
break
;
case
'd'
:
// arv[0] arv[1] arv[2]
// prog_name -d id
//-------------------------
// example: prog_name -d 100
if
(
argc
!=
3
)
{
usage
(
argv
[
0
]);
exit_code
=
EXIT_FAIL_ARGS
;
break
;
}
id
=
atoi
(
argv
[
2
]);
rc
=
del_student
(
fd
,
id
);
if
(
rc
<
0
)
exit_code
=
EXIT_FAIL_DB
;
break
;
case
'f'
:
// arv[0] arv[1] arv[2]
// prog_name -f id
//-------------------------
// example: prog_name -f 100
if
(
argc
!=
3
)
{
usage
(
argv
[
0
]);
exit_code
=
EXIT_FAIL_ARGS
;
break
;
}
id
=
atoi
(
argv
[
2
]);
rc
=
get_student
(
fd
,
id
,
&
student
);
switch
(
rc
)
{
case
NO_ERROR
:
print_student
(
&
student
);
break
;
case
SRCH_NOT_FOUND
:
printf
(
M_STD_NOT_FND_MSG
,
id
);
exit_code
=
EXIT_FAIL_DB
;
break
;
default:
printf
(
M_ERR_DB_READ
);
exit_code
=
EXIT_FAIL_DB
;
break
;
}
break
;
case
'p'
:
// arv[0] arv[1]
// prog_name -p
//-----------------
// example: prog_name -p
rc
=
print_db
(
fd
);
if
(
rc
<
0
)
exit_code
=
EXIT_FAIL_DB
;
break
;
case
'x'
:
// arv[0] arv[1]
// prog_name -x
//-----------------
// example: prog_name -x
// remember compress_db returns a fd of the compressed database.
// we close it after this switch statement
fd
=
compress_db
(
fd
);
if
(
fd
<
0
)
exit_code
=
EXIT_FAIL_DB
;
break
;
case
'z'
:
// arv[0] arv[1]
// prog_name -x
//-----------------
// example: prog_name -x
// HINT: close the db file, we already have fd
// and reopen db indicating truncate=true
close
(
fd
);
fd
=
open_db
(
DB_FILE
,
true
);
if
(
fd
<
0
)
{
exit_code
=
EXIT_FAIL_DB
;
break
;
}
printf
(
M_DB_ZERO_OK
);
exit_code
=
EXIT_OK
;
break
;
default:
usage
(
argv
[
0
]);
exit_code
=
EXIT_FAIL_ARGS
;
}
// dont forget to close the file before exiting, and setting the
// proper exit code - see the header file for expected values
close
(
fd
);
exit
(
exit_code
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment