Logo Search packages:      
Sourcecode: ha version File versions  Download package

machine.c

/***********************************************************************
  This file is part of HA, a general purpose file archiver.
  Copyright (C) 1995 Harri Hirvola

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
************************************************************************
      HA *nix specific routines
***********************************************************************/

#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <utime.h>
#include <time.h>
#include "ha.h"
#include "error.h"
#include "archive.h"

#define HA_ISVTX     0x0200
#define HA_ISGID     0x0400
#define HA_ISUID     0x0800
#define HA_IRUSR     0x0100
#define HA_IWUSR     0x0080 
#define HA_IXUSR     0x0040
#define HA_IRGRP     0x0020
#define HA_IWGRP     0x0010
#define HA_IXGRP     0x0008
#define HA_IROTH     0x0004
#define HA_IWOTH     0x0002
#define HA_IXOTH     0x0001
#define HA_IFMT      0xf000
#define HA_IFIFO     0x1000
#define HA_IFCHR     0x2000
#define HA_IFDIR     0x4000
#define HA_IFBLK     0x6000
#define HA_IFREG     0x8000
#define HA_IFLNK     0xa000
#define HA_IFSOCK    0xc000
#define HA_ISDIR(m)  ((m&HA_IFMT)==HA_IFDIR)
#define HA_ISCHR(m)  ((m&HA_IFMT)==HA_IFCHR)
#define HA_ISBLK(m)  ((m&HA_IFMT)==HA_IFBLK)
#define HA_ISLNK(m)  ((m&HA_IFMT)==HA_IFLNK)
#define HA_ISFIFO(m) ((m&HA_IFMT)==HA_IFIFO)
#define HA_ISSOCK(m) ((m&HA_IFMT)==HA_IFSOCK)

typedef struct {
    unsigned mtype; 
    unsigned attr;
    unsigned user;
    unsigned group;
} Mdhd;

#define MDHDLEN      7           /* Length of Mdhd in archive */

static Mdhd mdhd;
struct stat filestat;
      
static void sig_handler(int signo) {

    error(1,ERR_INT,signo);
}

void md_init(void) {

    signal(SIGINT,sig_handler);     
    signal(SIGTERM,sig_handler);    
    signal(SIGPIPE,sig_handler);    
    signal(SIGQUIT,sig_handler);    
    umask(0);
}

U32B md_systime(void) {

    return (U32B)time(NULL);
}

static mode_t md_tomdattr(U16B haattr) {

    mode_t mdattr;

    mdattr=0;
    if (haattr&HA_IRUSR) mdattr|=S_IRUSR;
    if (haattr&HA_IWUSR) mdattr|=S_IWUSR;
    if (haattr&HA_ISUID) mdattr|=S_ISUID;
    if (haattr&HA_IXUSR) mdattr|=S_IXUSR;
    if (haattr&HA_IRGRP) mdattr|=S_IRGRP;
    if (haattr&HA_IWGRP) mdattr|=S_IWGRP;
    if (haattr&HA_ISGID) mdattr|=S_ISGID;
    if (haattr&HA_IXGRP) mdattr|=S_IXGRP;
    if (haattr&HA_IROTH) mdattr|=S_IROTH;
    if (haattr&HA_IWOTH) mdattr|=S_IWOTH;
#ifdef S_ISVTX
    if (haattr&HA_ISVTX) mdattr|=S_ISVTX;
#endif
    if (haattr&HA_IXOTH) mdattr|=S_IXOTH;
    return mdattr;
}

static U16B md_tohaattr(mode_t mdattr) {

    U16B haattr;
    
    haattr=0;
    if (mdattr&S_IRUSR) haattr|=HA_IRUSR;
    if (mdattr&S_IWUSR) haattr|=HA_IWUSR;
    if (mdattr&S_ISUID) haattr|=HA_ISUID;
    if (mdattr&S_IXUSR) haattr|=HA_IXUSR;
    if (mdattr&S_IRGRP) haattr|=HA_IRGRP;
    if (mdattr&S_IWGRP) haattr|=HA_IWGRP;
    if (mdattr&S_ISGID) haattr|=HA_ISGID;
    if (mdattr&S_IXGRP) haattr|=HA_IXGRP;
    if (mdattr&S_IROTH) haattr|=HA_IROTH;
    if (mdattr&S_IWOTH) haattr|=HA_IWOTH;
    if (mdattr&S_IXOTH) haattr|=HA_IXOTH;
#ifdef S_ISVTX
    if (mdattr&S_ISVTX) haattr|=HA_ISVTX;
#endif
    if (S_ISDIR(mdattr)) haattr|=HA_IFDIR;
    else if (S_ISCHR(mdattr)) haattr|=HA_IFCHR;
    else if (S_ISBLK(mdattr)) haattr|=HA_IFBLK;
#ifdef S_ISLNK
    else if (S_ISLNK(mdattr)) haattr|=HA_IFLNK;
#endif
#ifdef S_ISFIFO
    else if (S_ISFIFO(mdattr)) haattr|=HA_IFIFO;
#endif
#ifdef S_ISSOCK
    else if (S_ISSOCK(mdattr)) haattr|=HA_IFSOCK;
#endif
    return haattr;
}

static char *attrstring(unsigned haattr) {

    static char as[11];

    sprintf(as,"%c%c%c%c%c%c%c%c%c%c",
          HA_ISFIFO(haattr)?'f':HA_ISSOCK(haattr)?'s':HA_ISLNK(haattr)?'l':
          HA_ISDIR(haattr)?'d':HA_ISCHR(haattr)?'c':HA_ISBLK(haattr)?'b':'-',
          (haattr&HA_IRUSR)?'r':'-',
          (haattr&HA_IWUSR)?'w':'-',
          (haattr&HA_ISUID)?(haattr&
                         HA_IXUSR)?'s':'S':(haattr&HA_IXUSR)?'x':'-',
          (haattr&HA_IRGRP)?'r':'-',
          (haattr&HA_IWGRP)?'w':'-',
          (haattr&HA_ISGID)?(haattr&
                         HA_IXGRP)?'s':'S':(haattr&HA_IXGRP)?'x':'-',
          (haattr&HA_IROTH)?'r':'-',
          (haattr&HA_IWOTH)?'w':'-',
          (haattr&HA_ISVTX)?(haattr&
                         HA_IXOTH)?'t':'T':(haattr&HA_IXOTH)?'x':'-'
          );
    return as;
}

void md_gethdr(int len, int mode) {
    
    static int longest=0;
    static unsigned char *buf=NULL;
    
    if (len>longest) {
      if (buf!=NULL) buf=realloc(buf,len);
      else buf=malloc(len);
      if (buf==NULL) error(1,ERR_MEM,"md_gethdr()");
      longest=len;
    }
    read(arcfile,buf,len);
    mdhd.mtype=buf[0];
    if (mdhd.mtype==UNIXMDH) {
      mdhd.attr=buf[1]|(buf[2]<<8);
      mdhd.user=buf[3]|(buf[4]<<8);
      mdhd.group=buf[5]|(buf[6]<<8);
    }
    else {
      switch (mode) {
        case M_DIR:
          mdhd.attr=md_tohaattr(DEF_DIRATTR);
          mdhd.attr|=HA_IFDIR;
          break;
        default:
          mdhd.attr=md_tohaattr(DEF_FILEATTR);
          break;
      }
    }
}

void md_puthdr(void) {
    
    unsigned char buf[MDHDLEN];
    
    buf[0]=UNIXMDH;
    buf[1]=mdhd.attr&0xff;
    buf[2]=(mdhd.attr>>8)&0xff;
    buf[3]=mdhd.user&0xff;
    buf[4]=(mdhd.user>>8)&0xff;
    buf[5]=mdhd.group&0xff;
    buf[6]=(mdhd.group>>8)&0xff;
    write(arcfile,buf,MDHDLEN);
}

int md_filetype(char *path, char *name) {
    
    char *fullpath;
    
    if (!strcmp(name,".") || !strcmp(name,"..")) return T_SKIP;
    fullpath=md_pconcat(0,path,name);
    if (lstat(fullpath,&filestat)<0) {
      error(0,ERR_STAT,fullpath);
      free(fullpath);
      return T_SKIP;
    }
    free(fullpath);
    if (filestat.st_ino==arcstat.st_ino) return T_SKIP;
    if (S_ISDIR(filestat.st_mode)) return T_DIR;
    if (S_ISREG(filestat.st_mode)) return T_REGULAR;
    return T_SPECIAL;
}

int md_newfile(void) {
    
    mdhd.attr=md_tohaattr(filestat.st_mode);
    mdhd.user=filestat.st_uid;
    mdhd.group=filestat.st_gid;
    return MDHDLEN;
}

int md_special(char *fullname, unsigned char **sdata) {
    
    static unsigned char *dat=NULL;
    int len;
    
    if (dat!=NULL) {
      free(dat);
      dat=NULL;
    }
    if (HA_ISCHR(mdhd.attr)||HA_ISBLK(mdhd.attr)) {
      if ((dat=malloc(sizeof(dev_t)))==NULL) error(1,ERR_MEM,"md_special()");
      *(dev_t*)dat=filestat.st_rdev;
      *sdata=dat;
      return sizeof(dev_t);
    }
    if (HA_ISLNK(mdhd.attr)) {
      if ((dat=malloc(1024))==NULL) error(1,ERR_MEM,"md_special()");
      if ((len=readlink(fullname,(char*)dat,1024))<0) 
        error(1,ERR_RDLINK,fullname);
      dat[len]=0;
      *sdata=dat;
      return len+1;
    }
    else {
      *sdata=dat;
      return 0;
    }
}

int md_mkspecial(char *ofname,unsigned sdlen,unsigned char *sdata) {
    
    if (mdhd.mtype!=UNIXMDH) {
      error(0,ERR_HOW,ofname);
      return 0;
    }
    if (HA_ISCHR(mdhd.attr)) {
      mknod(ofname,md_tomdattr(mdhd.attr)|S_IFCHR,*(dev_t*)sdata);
      if (useattr) chown(ofname,mdhd.user,mdhd.group);
      return 1;
    }
    else if (HA_ISBLK(mdhd.attr)) {
      mknod(ofname,md_tomdattr(mdhd.attr)|S_IFBLK,*(dev_t*)sdata);
      if (useattr) chown(ofname,mdhd.user,mdhd.group);
      return 1;
    }
#ifdef S_ISLNK
    else if (HA_ISLNK(mdhd.attr)) {
      if (symlink(ofname,(char*)sdata)<0) error(0,ERR_MKLINK,sdata,ofname);
      if (useattr) {
          chmod(ofname,md_tomdattr(mdhd.attr));
          chown(ofname,mdhd.user,mdhd.group);
      }
      return 1;
    }
#endif
#ifdef S_ISFIFO
    else if (HA_ISFIFO(mdhd.attr)) {
      if (mkfifo(ofname,md_tomdattr(mdhd.attr))<0) 
        error(0,ERR_MKFIFO,sdata,ofname);
      if (useattr) chown(ofname,mdhd.user,mdhd.group);
      return 1;
    }
#endif
    error(0,ERR_HOW,ofname);
    return 0;
}

void md_setfattrs(char *file) {
    
    if (useattr) {
      chmod(file,md_tomdattr(mdhd.attr));
      chown(file,mdhd.user,mdhd.group);
    }
}

void md_setft(char *file,U32B time) {
    
    struct utimbuf utb;
    
    utb.actime=time;
    utb.modtime=time;
    utime(file,&utb);
}

void md_listhdr(void) {
    
    printf("\n attr");
}

void md_listdat(void) {
    
    printf("\n %s",attrstring(mdhd.attr));
}

char *md_timestring(unsigned long t) {
    
    static char ts[22];
    struct tm *tim;     
    
    tim=localtime((long *)&t);
    sprintf(ts,"%04d-%02d-%02d  %02d:%02d",tim->tm_year+1900,tim->tm_mon+1,
          tim->tm_mday,tim->tm_hour,tim->tm_min);
    return ts;    
}

char *md_arcname(char *name_req) {
    
    int pos;
    char *newname;

    pos=strlen(name_req);
    if (pos>3 && 
      tolower(name_req[pos-1])=='a' && 
      tolower(name_req[pos-2])=='h' && 
      name_req[pos-3]=='.') return name_req;
    if ((newname=malloc(pos+4))==NULL) error(1,ERR_MEM,"md_arcname()");
    strcpy(newname,name_req);
    strcpy(newname+pos,".ha");
    return newname;
}

void md_truncfile(int fh, U32B len) {
    
    ftruncate(fh,len);  
}

char *md_tohapath(char *mdpath) {
    
    int i,j;
    static char *hapath=NULL;
    
    if (hapath!=NULL) free(hapath),hapath=NULL;
    j=strlen(mdpath);
    for (i=0;mdpath[i];++i) if (mdpath[i]!='.' && mdpath[i]!='/') break;
    while (i>0 && mdpath[i-1]=='.') --i;
    if (i==0) skipemptypath=1; 
    else skipemptypath=0;
    if ((hapath=malloc(j+1-i))==NULL) error(1,ERR_MEM,"md_tohapath()");
    strcpy(hapath,mdpath+i);
    for (i=0;hapath[i];++i) if (hapath[i]=='/') hapath[i]=0xff;
    return md_strcase(hapath);
}

char *md_tomdpath(char *hapath) {   
    
    int i;
    static char *mdpath=NULL;
    
    if (mdpath!=NULL) free(mdpath),mdpath=NULL;
    if ((mdpath=malloc(strlen(hapath)+1))==NULL) 
      error(1,ERR_MEM,"md_tomdpath()");
    strcpy(mdpath,hapath);
    for (i=0;mdpath[i];++i) if ((unsigned char)mdpath[i]==0xff) mdpath[i]='/';
    return mdpath;
}

char *md_strippath(char *mdfullpath) {
    
    int i;
    static char *plainpath=NULL;
    
    if (plainpath!=NULL) free(plainpath),plainpath=NULL;
    if ((plainpath=malloc(strlen(mdfullpath)+1))==NULL) 
      error(1,ERR_MEM,"md_strippath()");
    strcpy(plainpath,mdfullpath);
    for (i=strlen(plainpath)-1;i>=0;i--) {
      if (plainpath[i]=='/') break; 
    }
    plainpath[i+1]=0;
    return plainpath;
}

char *md_stripname(char *mdfullpath) {
    
    int i;
    static char *plainname=NULL;
    
    if (plainname!=NULL) free(plainname),plainname=NULL;
    if ((plainname=malloc(strlen(mdfullpath)+1))==NULL) 
      error(1,ERR_MEM,"md_stripname()");
    for (i=strlen(mdfullpath)-1;i>0;i--) {
      if (mdfullpath[i]=='/') {
          i++;
          break;
      }
    }
    strcpy(plainname,mdfullpath+i);
    return plainname;
}

char *md_pconcat(int delim2, char *head, char *tail) {
      
    char *newpath;
    int headlen,delim1;
    
    delim1=0;
    if ((headlen=strlen(head))!=0)  {
      if (head[headlen-1]!='/') delim1=1;
    }
    if ((newpath=malloc(headlen+strlen(tail)+delim2+delim1+1))==NULL) 
      error(1,ERR_MEM,"md_pconcat()");
    if (headlen!=0) strcpy(newpath,head);
    if (delim1) newpath[headlen]='/';
    strcpy(newpath+headlen+delim1,tail);
    if (delim2) strcpy(newpath+strlen(newpath),"/");
    return newpath;
}

int md_namecmp(char *pat, char *cmp) {

    if (*pat==0) return !*cmp;
    if (*pat=='?') {
      if (!*cmp) return 0;
      return md_namecmp(pat+1,cmp+1); 
    }
    if (*pat=='*') {
      if (*(pat+1)==0) return 1;
      for (;*cmp;++cmp) {
          if (md_namecmp(pat+1,cmp)) return 1;
      }
      return 0;
    }
    if (*pat=='\\') {
      ++pat;
      if (*pat==0) return 0;
    }
    if (*pat==*cmp) return md_namecmp(pat+1,cmp+1);
    return 0;
}




Generated by  Doxygen 1.6.0   Back to index