Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Restore boot manager after installing windows 7 over linux



  • Boot from the ubuntu Live CD.
  • Open the terminal from applications -> Accessories -> Terminal.
  • Then find the partition of your Ubuntu OS from the list generated with the command,
    • sudo fdisk -l
  •  If your ubuntu(linux) partion is sda6,
    • sudo mkdir /media/sda6
    • sudo mount /dev/sda6 /media/sda6
  • After that you have to reinstall the GRUB
    • sudo grub-install --root-directory=/media/sda5 /dev/sda
  • If everything went alright you should be able to reach the GRUB boot menu when you restart the computer. You can find more information from here.

Character Device Driver (for linux)


Little talk.....

This was my 3rd assignment in System programming lab(3rd year undergrad course). The main task of this assignment is to design a character driver which should exist in linux kernel. I make a kernel module which module implements a driver that exposes two character devices to user-space. Lets clarify some topics about this assignment.

Kernel Module

Modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system. For example, one type of module is the device driver, which allows the kernel to access hardware connected to the system. Without modules, we would have to build monolithic kernels and add new functionality directly into the kernel image. Besides having larger kernels, this has the disadvantage of requiring us to rebuild and reboot the kernel every time we want new functionality.

The Driver

Normally a device driver sits between some hardware and the kernel I/O subsystem. Its purpose is to give the kernel a consistent interface to the type of hardware it "drives". This way the kernel can communicate with all hardware of a given type through the same interface, even though the actual hardware differs.

About the driver

sakin_dev The figure to the left illustrates how my driver works. Basically it solves the producer-consumer problem. Here the two processes can be both producers and consumers. This resembles the functionality of a real hardware device driver, where both the hardware and the kernel can produce and consume data.
When a process writes (produces) to character device /dev/sakin-0 the data is stored in bounded buffer 1. If the buffer is full the process has to wait until another process has read from /dev/sakin-1.
When a process reads (consumes) from character device /dev/sakin-0 the data is read from bounded buffer 0. If the buffer is empty the process has to wait until another process has written to /dev/sakin-1.
Writes and reads to and from /dev/sakin-1 are handled in the same way.

Click this link to see my code.

Compiling and inserting the module

Makefile for compiling and creating the module sakin_dev.ko:
obj-m += sakin_dev.o
all:
 make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
 make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
script for loading the module sakin_dev.ko and creating the device file:
#file name sakin_load
#!/bin/sh
module_name="sakin_dev"
device_prefix="sakin-"
mode="664"
group="root"

# invoke insmod
# use a pathname, as newer modutils don't look in . by default
insmod ./${module_name}.ko

# retrieve major number
major=$(awk "\$2==\"$module_name\" {print \$1}" /proc/devices)

# Remove stale nodes and replace them, then give gid and perms
# Usually the script is shorter, it's scull that has several devices in it.

rm -f /dev/${device_prefix}[0-1]
mknod /dev/${device_prefix}0 c $major 0
mknod /dev/${device_prefix}1 c $major 1
chgrp $group /dev/${device_prefix}[0-1]
chmod $mode  /dev/${device_prefix}[0-1]
script for unloading the module sakin_dev.o and removing the device file:
#file name sakin_unload
#!/bin/sh
module_name="sakin_dev"
device_prefix="sakin-"

# invoke rmmod with all arguments we got
rmmod ${module_name}

# Remove stale nodes
rm -f /dev/${device_prefix}[0-1]
Now compile the module by running make. If the compilation succeeds there will now be a file called sakin_dev.ko which is the module. Create the necessary devices and insert the module by executing
./sakin_load
To remove the module and to delete the devices execute:
./sakin_unload

Functions and Macros:

int sakin_init_module( void ): init_function, Called when module is loaded into the kernel.
void sakin_cleanup_module( void ): cleanup_function, Called when module is unloaded from the kernel.
module_init(init_function): Macros that designate a modules initialization, defined in <linux/types.h>.
module_exit(cleanup_function): Macros that designate a modules cleanup functions, defined in <linux/types.h>.

static int sakin_open( struct inode*, struct file* ): Called when a process tries to open the device file.
static int sakin_release( struct inode*, struct file* ): Called when a process closes the device file.

static ssize_t sakin_read( struct file*, char*, size_t, loff_t* ): Called when a process, which already opened the sakin_dev file, attempts to read from it.
static int sakin_getwritespace(struct sakin_dev *dev, struct file *filp, const int c_minor): Wait for space for writing. Caller must hold device semaphore. On error the semaphore will be released before returning.
static int spacefree(struct sakin_dev *dev, const int c_minor): Return how much space is free.
static ssize_t sakin_write( struct file*, const char*, size_t, loff_t* ): Called when a process, which already opened the sakin_dev file, attempts to write to it.

dev_t MKDEV(unsigned int major, unsigned int minor): Macro that builds a dev_t data item from the major and minor numbers. Declared in <linux/types.h>.
int register_chrdev_region(dev_t first, unsigned int count, char *name): Allocating the device number, which is declared in <linux/fs.h>
void unregister_chrdev_region(dev_t first, unsigned int count): Freeing the device number, which is declared in <linux/fs.h>
container_of(pointer, type, field): A convenience macro that may be used to obtain a pointer to a structure from a pointer to some other structure contained within it.
void *kmalloc(size_t size, int flags): For allcating memory, which is declared in <linux/slab.h>
void kfree(void *ptr); For freeing memory, which is declared in <linux/slab.h>
static void sakin_setup_cdev(struct sakin_dev *dev, int index): Local function to setup the char device.
void cdev_init(struct cdev *cdev, struct file_operations *fops): Initializing and setting up the char device. Declared in <linux/cdev.h>
int cdev_add(struct cdev *dev, dev_t num, unsigned int count): Tell the kernel about the char device. Declared in <linux/cdev.h>
void cdev_del(struct cdev *dev): To remove a char device from the system. Declared in <linux/cdev.h>
unsigned int iminor(struct inode *inode),
unsigned int imajor(struct inode *inode):
used to obtain the major and minor number from an inode.
unsigned long copy_from_user (void *to, const void *from, unsigned long count),
unsigned long copy_to_user (void *to, const void *from, unsigned long count):
Copy data between user space and kernel space. Declared in <asm/uaccess.h>
void schedule(void): Selects a runnable process from the run queue. The chosen process can be current or a different one.
bool signal_pending(current): Tells whether current were awakened by a signal.
GFP_USER & GFP_KERNEL:
Flags that control how memory allocations are performed, from the least restrictive to the most. The GFP_USER and GFP_KERNEL priorities allow the current process to be put to sleep to satisfy the request.

Semaphore related functions defined in <asm/semaphore.h>
void sema_init(struct semaphore *sem, int val): Semaphore initialization.
void down(struct semaphore *sem): down puts the calling process into an uninterruptible sleep if need be.
int down_interruptible(struct semaphore *sem): down_interruptible, instead, can be interrupted by a signal.
int down_trylock(struct semaphore *sem): down_trylock does not sleep; instead, it returns immediately if the semaphore is unavailable.
void up(struct semaphore *sem): Code that locks a semaphore must eventually unlock it with up.

Sleep related functions defined in <linux/wait.h>
void init_waitqueue_head(wait_queue_head_t *queue);
DECLARE_WAIT_QUEUE_HEAD(queue):

The defined type for Linux wait queues. A wait_queue_head_t must be explicitly initialized with either init_waitqueue_head at runtime or DECLARE_WAIT_QUEUE_HEAD at compile time.
void wait_event(wait_queue_head_t q, int condition); //uninterruptible wait
int wait_event_interruptible(wait_queue_head_t q, int condition); //interruptible wait
int wait_event_timeout(wait_queue_head_t q, int condition, int time); //uninterruptible timeout wait
int wait_event_interruptible_timeout(wait_queue_head_t q, int condition, int time): //interruptible timeout wait
Cause the process to sleep on the given queue until the given condition evaluates to a true value.
void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state),
void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait):
Helper functions that can be used to code a manual sleep.
void wake_up(struct wait_queue **q); //uninterruptible
void wake_up_interruptible(struct wait_queue **q); //interruptible
void wake_up_nr(struct wait_queue **q, int nr);
void wake_up_interruptible_nr(struct wait_queue **q, int nr);
void wake_up_all(struct wait_queue **q);
void wake_up_interruptible_all(struct wait_queue **q):

Wake processes that are sleeping on the queue q. The _interruptible form wakes only interruptible processes. Normally, only one exclusive waiter is awakened, but that behavior can be changed with the _nr or _all forms.

Externel References:

The Linux Kernel Module Programming Guide
Linux Device Driver (Ch:2,3,5,6)

ls (my own implementation)


Little talk about 'ls' (since I have very small knowledge about it):
ls - list directory contents.

The 'ls' program lists information about files (of any type, including directories). Options and file arguments can be intermixed arbitrarily, as usual.
Know details about 'ls' in linux man page: http://unixhelp.ed.ac.uk/CGI/man-cgi?ls

Little talk about coding:
Probably I wouldn't write this code in my entire life unless I got it as my lab assignment :D. It was my 2nd year System Programming lab assignment. However, at first, it seemed very disgusting and painful task to me. But after started coding, it was fun to write the code.
I tried to make my 'ls' as like as linux's 'ls' implementation. Since I was not very familiar with linux, before doing this assignment, firstly I checked out all the options provided by the 'ls' process. Actually, I had to learn about all the functionalities it has :D.

Implementation:
I used c++ as the programming language. I have the name of a directory or file in dirent->d_name & and by using lstat() function, I retrieved all the information about a file or directory.
  • I saved each file or directory name and statistics in a vector.
  • Applying printing format given by the OPTIONS.
  • Print the corresponding information.
A closer look at lstat() in linux man page: http://linux.die.net/man/2/lstat
Here is my coding.........


/*
 * Course: CSE-326 System Programming Lab
 * Assignment No: 02
 * Assignment Name: ls — list directory contents
 * SYNOPSIS: ls [-AacdFfhiklnoqRrSstuw1] [file . . .]
 * Author: Sayef Azad Sakin
 * Roll: 1563
 * Language: c++
 */
 
#ifndef BLOCKSIZE
#define BLOCKSIZE 512
#endif
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <climits>
#include <algorithm>
using namespace std;

#define eps 1e-11
#define mx 1000

struct files{
 string name, full_path;
 struct stat st;
 files(string ps, string s, struct stat &ss){
  full_path = ps;
  name = s;
  st = ss;
 }
};

vector < files > name, dir_name[10], dir_path, rfile, rdir;
vector < files >:: iterator it;
bool flag[30];
int tot_dir;
char chk[] = {'A','a','c','d','F','f','h','i','k','l','n','o','q','R','r','S','s','t','u','w','1'};

bool comp(const files &a, const files &b){
 if(flag[15]){//-S
  if(a.st.st_size == b.st.st_size){
   if(flag[17]){//-t
    if(a.st.st_mtime == b.st.st_mtime)return (a.name<b.name);
    return (a.st.st_mtime < b.st.st_mtime);
   }
   return (a.name<b.name);
  }
  return (a.st.st_size > b.st.st_size);
 }
 if(flag[17]){//-t
  if(a.st.st_mtime == b.st.st_mtime)return (a.name<b.name);
  return (a.st.st_mtime < b.st.st_mtime);
 }
 if(flag[2]){//-c
  if(a.st.st_ctime == b.st.st_ctime)return (a.name<b.name);
  return (a.st.st_ctime < b.st.st_ctime);
 }
 if(flag[18]){//-u
  if(a.st.st_atime == b.st.st_atime)return (a.name<b.name);
  return (a.st.st_atime < b.st.st_atime);
 }
 return (a.name<b.name);
}

int getfile(files fdes);
int chkflag(char *str);
void print(const files fdes);

int main(int argc, char **argv){
 int argpos, i, sz;
 bool ok;
 char path[mx], cwd[mx];
 dirent *dirp;
 DIR *dp;
 struct stat f_stat;
 //initialize();
 //parsing starts here
 ok = 0;
 for(argpos = 1; argpos < argc; argpos++){
  if(argv[argpos][0]=='-'){
   if(chkflag(argv[argpos])==-1){puts("argument error");return 2;}
  }
  else{
   if (lstat(argv[argpos], &f_stat) == -1){puts("statistics error");return -1;}
   if(S_ISREG(f_stat.st_mode) || !strcmp(argv[argpos],".") || !strcmp(argv[argpos],".."))rfile.push_back(files(argv[argpos],argv[argpos],f_stat));
   else if(S_ISDIR(f_stat.st_mode))rdir.push_back(files(argv[argpos],argv[argpos],f_stat));
   ok = 1;
  }
 }
 if(!ok){
  if( !getcwd(cwd,mx) ) return 1;
  
  if( !(dp = opendir(cwd)) ){puts("error on opening current directory");return 3;}
  while( (dirp = readdir(dp)) ){
   strcpy(path,".");
   strcat(path,"/");
   strcat(path,dirp->d_name);
   if (lstat(path, &f_stat) == -1){puts("statistics error");return -1;}
   if(S_ISREG(f_stat.st_mode) || !strcmp(dirp->d_name,".") || !strcmp(dirp->d_name,".."))rfile.push_back(files(path,dirp->d_name,f_stat));
   else if(S_ISDIR(f_stat.st_mode))rdir.push_back(files(path,dirp->d_name,f_stat));
  }
  if( closedir(dp) < 0 ){puts("can't close directory");return -1;}
 }
 //parsing ends here

 //sorting starts here
 sort(rfile.begin(),rfile.end(),comp);
 sort(rdir.begin(),rdir.end(),comp);
 if(flag[14]){//-r
  reverse(rfile.begin(),rfile.end());
  reverse(rdir.begin(),rdir.end());
 }
 //sorting ends here
 
 sz = rfile.size();
 for(i=0;i<sz;i++)
  print(rfile[i]);
 if(!ok || flag[3]){//-d
  sz = rdir.size();
  for(i=0;i<sz;i++)
   print(rdir[i]);
  return 0;
 }
 puts("");
 sz = rdir.size();
 
 if(ok || flag[13]){//-R
  for(i=0;i<sz;i++){
   cout << rdir[i].name << ":(under this direcotry) " << endl;
   if(getfile(rdir[i])==-1)return 5;
  }
 }
 return 0;
}

int getfile(files fdes){
 dirent *dirp;
 DIR *dp;
 vector < files > tfile, tdir;
 struct stat file_stat;
 char path[mx], tpath[mx];
 int sz, i;
 strcpy(path,fdes.full_path.c_str());
 if( !(dp = opendir(path)) ){puts("error on opening directory");return -1;}
 while( (dirp = readdir(dp)) ){
  strcpy(tpath,path);
  sz = strlen(tpath);
  if(tpath[sz-1]!='/'){
   tpath[sz] = '/'; tpath[sz+1] = 0;
  }
  strcat(tpath,dirp->d_name);
  //printf("%s\n",tpath);
  if (lstat(tpath, &file_stat) == -1){puts("statistics error");return -1;}
  if(S_ISREG(file_stat.st_mode) || !strcmp(dirp->d_name,".") || !strcmp(dirp->d_name,".."))tfile.push_back(files(tpath,dirp->d_name,file_stat));
  else if(S_ISDIR(file_stat.st_mode))tdir.push_back(files(tpath,dirp->d_name,file_stat));
 }
 if( closedir(dp) < 0 ){puts("can't close directory");return -1;}
 
 //sorting starts here
 sort(tfile.begin(),tfile.end(),comp);
 sort(tdir.begin(),tdir.end(),comp);
 if(flag[14]){//-r
  reverse(tfile.begin(),tfile.end());
  reverse(tdir.begin(),tdir.end());
 }
 //sorting ends here
 
 sz = tfile.size();
 for(i=0;i<sz;i++)
  print(tfile[i]);
 sz = tdir.size();
 for(i=0;i<sz;i++)
  print(tdir[i]);
 puts("");
 if(flag[3])return 0;//-d
 if(flag[13]){
  sz = tdir.size();
  for(i=0;i<sz;i++){
   cout << tdir[i].name << ":(under this direcotry) " << endl;
   if(getfile(tdir[i])==-1)return -1;
  }
 }
 return 0;
}

int chkflag(char *str){
 bool ok;
 int i,j;
 for(i = 1;str[i]; i++){
  if(str[i]=='R' && flag[3])continue;
  ok = 0;
  for(j=0;j<21;j++){
   if(chk[j]=='h' && str[i]=='k')flag[j] = 0;
   else if(chk[j]=='k' && str[i]=='h')flag[j] = 0;
   else if(chk[j]=='1' && str[i]=='l')flag[j] = 0;
   else if(chk[j]=='l' && str[i]=='1')flag[j] = 0;
   else if(chk[j]=='c' && str[i]=='u')flag[j] = 0;
   else if(chk[j]=='u' && str[i]=='c')flag[j] = 0;
   else if(chk[j]=='q' && str[i]=='w')flag[j] = 0;
   else if(chk[j]=='w' && str[i]=='q')flag[j] = 0;
   else if(chk[j]=='R' && str[i]=='d')flag[j] = 0;
   
   if(chk[j]==str[i]){ok=1;break;}
  }
  if(ok)flag[j] = 1;
  else return -1;
 }
 return 0;
}

void print(const files fdes){
 double sz;
 struct tm *ts;
 char ptime[20];
 struct passwd *ps;
 struct group *gr;
 sz = fdes.st.st_size;
 if(!flag[1] && (fdes.name == "." || fdes.name == ".."))return;
 if(flag[7])printf("%u ",fdes.st.st_ino);//-i
 if(flag[16]){//-s
  sz = fdes.st.st_blocks*512;
  if(!flag[6] && !flag[8]){
   sz /=1024;
   printf("%5.0lf ",ceil(sz));
  }
 }
 if(flag[6] && flag[16]){//-h
  if(sz>1073741824 || fabs(sz-1073741824)<eps){
   sz /= 1073741824;
   printf("%.1lfG ",sz+eps);
  }
  else if(sz>1048576 || fabs(sz-1048576)<eps){
   sz /= 1048576;
   printf("%.1lfM ",sz+eps);
  }
  else if(sz>1024 || fabs(sz-1024)<eps){
   sz /= 1024;
   printf("%.1lfK ",sz+eps);
  }
  else printf("%.0lf ",sz);
 }
 if(flag[8] && flag[16]){//-k
  sz /= 1024;
  printf("%5.0lf ",ceil(sz));
 }
 if(flag[9] || flag[10] || flag[13]){//-l & -n
  //file mode
  //entry type
  if(S_ISBLK(fdes.st.st_mode))printf("b");
  else if(S_ISCHR(fdes.st.st_mode))printf("c");
  else if(S_ISDIR(fdes.st.st_mode))printf("d");
  else if(S_ISLNK(fdes.st.st_mode))printf("l");
  else if(S_ISSOCK(fdes.st.st_mode))printf("s");
  else if(S_ISFIFO(fdes.st.st_mode))printf("p");
  else if(S_ISREG(fdes.st.st_mode))printf("-");
  //owner permission
  printf((fdes.st.st_mode & S_IRUSR)?"r":"-");
  printf((fdes.st.st_mode & S_IWUSR)?"w":"-");
  if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111)
   printf((fdes.st.st_mode & S_ISUID)?"s":"x");
  else
   printf((fdes.st.st_mode & S_ISUID)?"S":"-");
  //group permission
  printf((fdes.st.st_mode & S_IRGRP)?"r":"-");
  printf((fdes.st.st_mode & S_IWGRP)?"w":"-");
  if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111)
   printf((fdes.st.st_mode & S_ISGID)?"s":"x");
  else
   printf((fdes.st.st_mode & S_ISGID)?"S":"-");
  //other permission
  printf((fdes.st.st_mode & S_IROTH)?"r":"-");
  printf((fdes.st.st_mode & S_IWOTH)?"w":"-");
  if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111)
   printf((fdes.st.st_mode & S_ISVTX)?"t":"-");
  else
   printf((fdes.st.st_mode & S_ISVTX)?"T":"-");
  
  //number of links
  printf(" %u",fdes.st.st_nlink);
  
  //user name & group name
  if(flag[10])printf(" %5u%5u",fdes.st.st_uid,fdes.st.st_gid);
  else{
   ps = getpwuid(fdes.st.st_uid);
   printf(" %s ",ps->pw_name);
   if(!flag[13]){
    gr = getgrgid(fdes.st.st_gid);
    printf(" %s",gr->gr_name);
   }
  }
  
  //no of bytes
  sz = fdes.st.st_size;
  if(flag[6]){//-h
   if(sz>1073741824 || fabs(sz-1073741824)<eps){
    sz /= 1073741824;
    printf("%10.1lfG ",sz+eps);
   }
   else if(sz>1048576 || fabs(sz-1048576)<eps){
    sz /= 1048576;
    printf("%10.1lfM ",sz+eps);
   }
   else if(sz>1024 || fabs(sz-1024)<eps){
    sz /= 1024;
    printf("%10.1lfK ",sz+eps);
   }
   else printf("%10.0lf ",sz);
  }
  else if(flag[8]){//-k
   sz /= 1024;
   printf("%10.0lf ",ceil(sz));
  }
  else printf("%10.0lf ",sz);
  
  //year-month-day hh:mm
  ts = localtime(&fdes.st.st_mtime);
  strftime(ptime, sizeof(ptime), "%Y-%m-%d %H:%M", ts);
  printf("%s ", ptime);
 }
 
 cout << fdes.name;
 if(flag[4]){//-F
  if(S_ISDIR(fdes.st.st_mode))printf("/");
  else if(S_ISREG(fdes.st.st_mode) && fdes.st.st_mode & 0111)printf("*");
  else if(S_ISLNK(fdes.st.st_mode))printf("@");
  //else if(S_IFWHT(fdes.st.st_mode))printf("@");
  else if(S_ISSOCK(fdes.st.st_mode))printf("=");
  else if(S_ISFIFO(fdes.st.st_mode))printf("|");
 }
 puts("");
}

MAKEFILE (at a glance)


Sample code
 
project1: data.o main.o io.o
        cc data.o main.o io.o -o project1
data.o: data.c data.h
        cc -c data.c
main.o: data.h io.h main.c
        cc -c main.c
io.o: io.h io.c
        cc -c io.c #this is a comment

Syntex
target : source file(s)
command (must be preceded by a tab)

#command to use user defined makefile name
make -f mymakefile

Macros in make
The make program allows to use macros, which are similar to variables, to store names of files. The format is as follows:
OBJECTS = data.o io.o main.o
Whenever you want to have make expand these macros out when it runs, type the following corresponding string $(OBJECTS).

Here is sample Makefile again, using a macro.
OBJECTS = data.o main.o io.o
project1: $(OBJECTS)
        cc $(OBJECTS) -o project1
data.o: data.c data.h
        cc -c data.c
main.o: data.h io.h main.c
        cc -c main.c
io.o: io.h io.c
        cc -c io.c
You can also specify a macro's value when running make, as follows:
make 'OBJECTS=data.o newio.o main.o' project1
This overrides the value of OBJECTS in the Makefile

Special Macros
CC:
Contains the current C compiler. Defaults to cc.
CFLAGS:
Special options which are added to the built-in C rule.
$@:
Full name of the current target.
$?:
A list of files for current dependency which are out-of-date.
$<:
The source file of the current (single) dependency.

External Links:
http://www.eng.hawaii.edu/Tutor/Make/1.html
http://www.opussoftware.com/tutorial/TutMakefile.htm