⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uxspec.c

📁 open arj source
💻 C
字号:
/* * $Id: uxspec.c,v 1.5 2003/07/15 16:35:18 andrew_belov Exp $ * --------------------------------------------------------------------------- * This module handles the UNIX special files and the owner IDs. * */#include "arj.h"#if TARGET==UNIX #include <pwd.h> #include <grp.h>#endifDEBUGHDR(__FILE__)                      /* Debug information block *//* UXSPECIAL block types */#define UXSB_FIFO               0x00#define UXSB_HLNK               0x01#define UXSB_LNK                0x02#define UXSB_BLK                0x03#define UXSB_CHR                0x04#define UXSB_ID_BITS               3    /* Bits for block ID */#define UXSB_SIZE_BITS (8-UXSB_ID_BITS) /* Bits for block size */#define UXSB_SIZE_THRESHOLD ((1<<UXSB_SIZE_BITS)-1)  /* When to switch to 2-byte fmt. */#define MK_UXSB(id, size) (((unsigned char)(id)<<UXSB_SIZE_BITS)|(unsigned char)(size))#define UXSB_GET_ID(c) ((unsigned char)(c)>>UXSB_SIZE_BITS)#define UXSB_GET_SIZE(c) ((unsigned char)(c)&((1<<UXSB_SIZE_BITS)-1))#define UXSB_CALC_SIZE(s) (s+((s<UXSB_SIZE_THRESHOLD)?1:3))/* Reference partition support */#if SFX_LEVEL>=ARJ&&TARGET==UNIX#define MAX_DEVS                 256    /* # of devs specified by the user */static dev_t user_devs[MAX_DEVS];static unsigned int total_devs=0;static int excl_mode=1;#endif/* * UNIX special file handling *//* Given a raw UXSPECIAL block, reports its size */unsigned int get_uxspecial_size(char FAR *blk){ int l; l=UXSB_GET_SIZE(blk[0]); if(l==UXSB_SIZE_THRESHOLD)  return(mget_word(blk+1)+3); else  return(l+1);}/* Fills in the header size fields, returning a pointer to the data area */static char FAR *fill_hdr_size(char FAR *dest, int type, int size){ if(size<UXSB_SIZE_THRESHOLD) {  mput_byte(MK_UXSB(type, size), dest);  return(dest+1); } else {  mput_byte(MK_UXSB(type, UXSB_SIZE_THRESHOLD), dest);  mput_word(size, dest+1);  return(dest+3); }}/* Stores the UNIX special file data in archive fields */#if SFX_LEVEL>=ARJint query_uxspecial(char FAR **dest, char *name, struct file_properties *props){ #if TARGET==UNIX  struct stat st;  char tmp_name[FILENAME_MAX-1];  int l;  char FAR *dptr;  int hardlink=0;  if(lstat(name, &st)==-1)   return(-1);  if(!S_ISDIR(st.st_mode)&&st.st_nlink>1&&props->islink)   hardlink=1;  if(S_ISFIFO(st.st_mode))   mput_byte(MK_UXSB(UXSB_FIFO, 0), (*dest=(char FAR *)farmalloc_msg(1)));  else if(S_ISLNK(st.st_mode)||hardlink)  {   if(hardlink)   {    retrieve_entry(tmp_name, NULL, &flist_main, props->l_search.ref);    l=strlen(tmp_name);   }   else   {    if((l=readlink(name, tmp_name, sizeof(tmp_name)))<=0)     return(-1);   }   *dest=(char FAR *)farmalloc_msg(UXSB_CALC_SIZE(l));   dptr=fill_hdr_size(*dest, hardlink?UXSB_HLNK:UXSB_LNK, l);   far_memmove(dptr, (char FAR *)tmp_name, l);  }  else if(S_ISCHR(st.st_mode)||S_ISBLK(st.st_mode))  {   *dest=(char FAR *)farmalloc_msg(UXSB_CALC_SIZE(sizeof(st.st_rdev)));   dptr=fill_hdr_size(*dest, S_ISCHR(st.st_mode)?UXSB_CHR:UXSB_BLK, sizeof(st.st_rdev));   far_memmove(dptr, (char FAR *)&st.st_rdev, sizeof(st.st_rdev));  }  else   return(-1);                          /* Unusual file type, report warning */ #else  return(-1); #endif return(0);}#endif/* Restores the UNIX special file data */int set_uxspecial(char FAR *storage, char *name){ #if TARGET==UNIX  char FAR *dptr;  int l, id;  char tmp_name[FILENAME_MAX];  int rc;  unlink(name);  l=UXSB_GET_SIZE(storage[0]);  if(l==UXSB_SIZE_THRESHOLD)   l=mget_word(storage+1);  id=UXSB_GET_ID(storage[0]);  dptr=storage+((UXSB_GET_SIZE(*storage)==UXSB_SIZE_THRESHOLD)?3:1);  switch(id)  {   case UXSB_FIFO:    rc=mkfifo(name, 0644);    return(rc?UXSPEC_RC_ERROR:0);   case UXSB_HLNK:   case UXSB_LNK:    #if SFX_LEVEL>=ARJ         if(id==UXSB_HLNK)     {      if(suppress_hardlinks==SHL_DROP)       return(UXSPEC_RC_SUPPRESSED);      else if(suppress_hardlinks==SHL_SOFT)       id=UXSB_LNK;     }    #endif    if(l>=sizeof(tmp_name))     l=sizeof(tmp_name)-1;    far_memmove((char FAR *)tmp_name, dptr, l);    tmp_name[l]='\0';    rc=(id==UXSB_HLNK)?link(tmp_name, name):symlink(tmp_name, name);    if(!rc)     return(0);    return(errno==EPERM?UXSPEC_RC_NOLINK:UXSPEC_RC_ERROR);   case UXSB_BLK:   case UXSB_CHR:    /* Check for platform mismatch */    if(sizeof(dev_t)!=l)     return(UXSPEC_RC_FOREIGN_OS);    rc=mknod(name, 0644|((id==UXSB_BLK)?S_IFBLK:S_IFCHR), *(dev_t FAR *)dptr);    return(rc?UXSPEC_RC_ERROR:0);  } #else  return(UXSPEC_RC_ERROR); #endif}/* Statistics report */void uxspecial_stats(char FAR *storage, int format){ #if TARGET==UNIX  FMSGP fm; #endif #if SFX_LEVEL>=ARJ  char tmp[FILENAME_MAX-1];  char FAR *dptr;  int i, l, m, id; #endif if(format==UXSTATS_SHORT) {  /* Only relevant under UNIX when extracting the files */#if TARGET==UNIX    switch(UXSB_GET_ID(storage[0]))  {   case UXSB_FIFO:    fm=M_UXSPECIAL_FIFO;    break;   case UXSB_HLNK:    fm=M_UXSPECIAL_HLNK;    break;   case UXSB_LNK:    fm=M_UXSPECIAL_LNK;    break;   case UXSB_CHR:    fm=M_UXSPECIAL_CHR;    break;   case UXSB_BLK:    fm=M_UXSPECIAL_BLK;    break;   default:    return;  }  msg_cprintf(0, fm);  fputc(' ', new_stdout);#endif }#if SFX_LEVEL>=ARJ else {  l=UXSB_GET_SIZE(storage[0]);  if(l==UXSB_SIZE_THRESHOLD)   l=mget_word(storage+1);  id=UXSB_GET_ID(storage[0]);  dptr=storage+((UXSB_GET_SIZE(*storage)==UXSB_SIZE_THRESHOLD)?3:1);  switch(id)  {   case UXSB_FIFO:    msg_cprintf(0, M_UXLIST_FIFO);    break;   case UXSB_HLNK:   case UXSB_LNK:    if(l>=sizeof(tmp))     l=sizeof(tmp)-1;    far_memmove((char FAR *)tmp, dptr, l);    tmp[l]='\0';    msg_cprintf(0, (id==UXSB_HLNK)?M_UXLIST_HLNK:M_UXLIST_LNK, tmp);    break;   case UXSB_BLK:   case UXSB_CHR:    m=0;    tmp[0]='\0';    for(i=0; i<l&&m<sizeof(tmp)-4; i++)     m+=sprintf(tmp+m, "%02x ", (unsigned char)dptr[i]);    if(m>0)     tmp[m-1]='\0';    msg_cprintf(0, (id==UXSB_BLK)?M_UXLIST_BLK:M_UXLIST_CHR, tmp);    break;  } }#endif}/* Given a raw UXSPECIAL block, reports its size */unsigned int get_owner_size(char FAR *blk){ return(*(unsigned char *)blk+1);}/* Queries the file owner */#if SFX_LEVEL>=ARJint query_owner(char FAR **dest, char *name, int how_to_resolve){ #if TARGET==UNIX  struct passwd *pw;  struct group *gr;  struct stat st;  unsigned int l, lg, lt;  char FAR *dst;  if(lstat(name, &st)==-1)   return(-1);  if(how_to_resolve==OWNSTG_CHAR||how_to_resolve==OWNSTG_CHAR_GID)  {   if((pw=getpwuid(st.st_uid))==NULL)    return(-1);   l=strlen(pw->pw_name);   if(l>=256)   {    return(-1);   }   dst=(char FAR *)farmalloc_msg(l+1);    dst[0]=(unsigned char)l;   far_memmove(dst+1, (char FAR *)pw->pw_name, l);   /* Now locate the GID entry if we have to, otherwise shut down */   if(how_to_resolve!=OWNSTG_CHAR_GID)   {    *dest=dst;    return(0);   }   if((gr=getgrgid(st.st_gid))==NULL)    return(-1);   lg=strlen(gr->gr_name);   if(lg>=256)    return(-1);   lt=lg+l+1;   dst=(char FAR *)farrealloc_msg(dst, lt+1);    dst[0]=(unsigned char)lt;   dst[l+1]='\0';   far_memmove(dst+l+2, (char FAR *)gr->gr_name, lg);   *dest=dst;  }  else  {   *dest=(char FAR *)farmalloc_msg(9);   *dest[0]=8;   mput_dword((unsigned long)st.st_uid, *dest+1);   mput_dword((unsigned long)st.st_gid, *dest+5);  }  return(0); #else  return(-1); #endif}#endif/* Restores the file properties */int set_owner(char FAR *storage, char *name, int resolve){ #if TARGET==UNIX  struct passwd *pw;  struct group *gr;  char tmp[513];  int l, i, rc;  gid_t gid;  l=*(unsigned char FAR *)storage;  if(l>=sizeof(tmp))   return(-1);                          /* Prevent overruns */  if(resolve)  {   far_memmove((char FAR *)tmp, storage+1, l);   tmp[l]='\0';   i=strlen(tmp);   if((pw=getpwnam(tmp))==NULL)    return(-1);   gid=pw->pw_gid;   /* Is the group information hidden somewhere? The group may be allowed to      be nonexistent, in this case we'll simply fall back to the "default"      group received from getpwnam() */   if(i<l-1&&(gr=getgrnam(tmp+i+1))!=NULL)    gid=gr->gr_gid;   rc=lchown(name, pw->pw_uid, gid);   return(rc);  }  else  {   if(l!=8)    return(-1);   return(lchown(name, mget_dword(storage+1), mget_dword(storage+5)));  } #else  return(-1); #endif}/* Report the owner */#if SFX_LEVEL>=ARJvoid owner_stats(char FAR *storage, int resolve){ char tmp[256]; int l, i; l=*(unsigned char FAR *)storage; if(resolve) {  far_memmove((char FAR *)tmp, storage+1, l);  tmp[l]='\0';  i=strlen(tmp);  if(i<l-1)   tmp[i]='/';                          /* Format as "<user>/<group>" */ } else {  if(l==8)   msg_sprintf(tmp, M_OWNER_ID, mget_dword(storage+1), mget_dword(storage+5));  else   strcpy(tmp, "???"); } msg_cprintf(0, M_OWNER_LIST, tmp);}#endif/* * Device-specific archiving */#if SFX_LEVEL>=ARJ&&TARGET==UNIX/* Sets inclusion/exclusion mode */void set_dev_mode(int is_excl){ excl_mode=is_excl;}/* Add a device specification to the pool */int add_dev(char *name){ struct stat st; unsigned int i; if(total_devs>=MAX_DEVS||stat(name, &st))  return(-1); for(i=0; i<total_devs; i++)  if(user_devs[i]==st.st_dev)   return(-1); user_devs[total_devs++]=st.st_dev; return(0);}/* Validate a file against the device spec */int is_dev_allowed(dev_t dev){ int i; for(i=0; i<total_devs; i++) {  if(user_devs[i]==dev)   return(!excl_mode); } return(excl_mode);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -