📄 growisofs.c
字号:
#define VOLDESC_OFF 16#define DVD_BLOCK (32*1024)static unsigned int from_733 (unsigned char *s){ unsigned int ret=0; ret |= s[0]; ret |= s[1]<<8; ret |= s[2]<<16; ret |= s[3]<<24; return ret;}static void to_733 (unsigned char *s,unsigned int val){ s[0] = (val) & 0xFF; s[1] = (val>>8) & 0xFF; s[2] = (val>>16) & 0xFF; s[3] = (val>>24) & 0xFF; s[4] = (val>>24) & 0xFF; s[5] = (val>>16) & 0xFF; s[6] = (val>>8) & 0xFF; s[7] = (val) & 0xFF;}static pwrite64_t pwrite64_method = pwrite64;/* * Page-aligned 2*DVD_BLOCK=64KB large buffer, second 32KB contain * "next" session volume descriptors that were written in the beginning * of current recording... */static char *the_buffer;/* * id_fd is passed to mkisofs, out_fd - to pwrite and ioctl_fd - to ioctl. */static int in_fd=-1,out_fd=-1;#ifndef INVALID_HANDLE#define INVALID_HANDLE ((void *)-1)#endifstatic void *ioctl_handle=INVALID_HANDLE;#define ioctl_fd ((long)ioctl_handle)static int poor_man=-1, zero_image=0, quiet=1, overburn=0, no_tty_check=0, dry_run=0, dao_size=0, no_4gb_check=0, layer_break=0;int dvd_compat=0, test_write=0, no_reload=0, mmc_profile=0, wrvfy=0;double speed_factor=0.0;char *ioctl_device;int _argc;char **_argv;#if defined(__linux)#include <linux/cdrom.h>#include <sys/ioctl.h>#include <linux/raw.h>#include <sys/prctl.h>#include <sys/syscall.h>#ifndef _LINUX_WAIT_H#define _LINUX_WAIT_H /* linux headers are impaired */#endif#include <linux/capability.h>char *find_raw_device(struct stat64 *sb){ int i,rawctl; dev_t dev_major,dev_minor; char *ret=NULL; struct raw_config_request req; static char rawdevname[24] = ""; if (!S_ISBLK(sb->st_mode)) return NULL; dev_major = major (sb->st_rdev); dev_minor = minor (sb->st_rdev); if ((rawctl=open ("/dev/rawctl",O_RDONLY)) < 0) return NULL; for (i=1;i<256;i++) { req.raw_minor = i; if (ioctl(rawctl,RAW_GETBIND,&req) < 0) break; if (req.block_major == dev_major && req.block_minor == dev_minor) { sprintf (rawdevname,"/dev/raw/raw%d",i); ret = rawdevname; break; } } close (rawctl); return ret;}char *setup_fds (char *device){ char *odevice; uid_t uid=getuid(); struct stat64 sb,sc; int fd; /* * I ignore return values from set{re}uid calls because if * they fail we have no privileges to care about and should * just proceed anyway... */#if 0#define GET_REAL /* * Get real, but preserve saved uid. I count that user is * logged on console and therefore owns the 'device' [this * is a PAM's resposibility to arrange]. */ setreuid ((uid_t)-1,uid);#else /* * More "traditional" set-root-uid behaviour. I assume that if * administrator has installed growisofs set-root-uid, then * [s]he consciously wanted to grant access to /dev/scdN to * everybody, not just console user. */#endif if ((in_fd = open64 (device,O_RDONLY)) < 0) if (!(errno == ENOMEDIUM || errno == EMEDIUMTYPE) || (in_fd = open64 (device,O_RDONLY|O_NONBLOCK)) < 0) fprintf (stderr,":-( unable to open64(\"%s\",O_RDONLY): ",device), perror (NULL), exit (FATAL_START(errno));#ifdef GET_REAL setreuid ((uid_t)-1,uid);#endif if (fstat64(in_fd,&sb) < 0) fprintf (stderr,":-( unable to stat64(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (!S_ISBLK(sb.st_mode)) { setuid(uid); /* drop all privileges */ close (in_fd); /* reopen as mortal */ if ((in_fd = open64 (device,O_RDONLY)) < 0) fprintf (stderr,":-( unable to re-open64(\"%s\",O_RDONLY): ", device), perror (NULL), exit (FATAL_START(errno)); open_rw: if ((out_fd = open64 (device,O_RDWR)) < 0) fprintf (stderr,":-( unable to open64(\"%s\",O_RDWR): ",device), perror (NULL), exit (FATAL_START(errno)); if (fstat64(out_fd,&sc) < 0) fprintf (stderr,":-( unable to stat64(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (sb.st_dev!=sc.st_dev || sb.st_ino!=sc.st_ino) fprintf (stderr,":-( %s: race condition detected!\n",device), exit(FATAL_START(EPERM)); opened_rw: poor_man = 0; if (ioctl_handle!=INVALID_HANDLE) close (ioctl_fd), ioctl_handle = INVALID_HANDLE; setuid (uid); /* drop all privileges */ return device; } /* * O_RDWR is expected to provide for none set-root-uid * execution under Linux kernel 2.6[.8]. If it fails * [as under 2.6.8], CAP_SYS_RAWIO in combination * with set-root-uid should fill in for the kernel * deficiency... */ if ((fd = open64 (device,O_RDWR|O_NONBLOCK)) >= 0) ioctl_handle=(void *)(long)fd; else ioctl_handle=(void *)(long)dup(in_fd); /* * get_mmc_profile terminates the program if ioctl_handle is * not an MMC unit... */ mmc_profile = get_mmc_profile (ioctl_handle); /* Consume media_changed flag */ if (ioctl (ioctl_fd,CDROM_MEDIA_CHANGED,CDSL_CURRENT) < 0) { fprintf (stderr,":-( %s: CD_ROM_MEDIA_CHANGED ioctl failed: ", device), perror (NULL), exit (FATAL_START(errno)); } switch (mmc_profile&0xFFFF) { case 0x11: /* DVD-R */ case 0x13: /* DVD-RW Restricted Overwrite */ case 0x14: /* DVD-RW Sequential */ case 0x1B: /* DVD+R */ case 0x2B: /* DVD+R Double Layer */ open_poor_man: poor_man = 1; out_fd = dup(ioctl_fd);#if defined(PR_SET_KEEPCAPS) if (prctl(PR_SET_KEEPCAPS,1) == 0) do {#if defined(_LINUX_CAPABILITY_VERSION) && defined(CAP_SYS_RAWIO) && defined(SYS_capset) struct __user_cap_header_struct h; struct __user_cap_data_struct d; h.version = _LINUX_CAPABILITY_VERSION; h.pid = 0; d.effective = 0; d.permitted = 1<<CAP_SYS_RAWIO; d.inheritable = 0; if (syscall(SYS_capset,&h,&d) < 0) break; /* drop all privileges & effective capabilities */ /* setuid(uid) seems to preserve saved uid after dropping CAP_SETUID above... */ setresuid (uid,uid,uid); d.effective = 1<<CAP_SYS_RAWIO; if (syscall(SYS_capset,&h,&d) < 0) break;#endif } while (0);#endif setuid (uid); /* drop all privileges */ return ioctl_device=device; case 0x1A: /* DVD+RW */ case 0x12: /* DVD-RAM */ if (poor_man>0) goto open_poor_man; break; default: fprintf (stderr,":-( %s: media is not recognized as " "recordable DVD: %X\n",device,mmc_profile); exit (FATAL_START(EMEDIUMTYPE)); } /* * Attempt to locate /dev/raw/raw* */#ifdef GET_REAL#undef GET_REAL setreuid((uid_t)-1,0); /* get root for a /dev/raw sake */#endif if ((odevice=find_raw_device (&sb))) /* /dev/raw */ { if ((out_fd=open64 (odevice,O_RDWR)) < 0) { if (errno == EROFS) /* must be unpatched kernel */ goto open_poor_man; else fprintf (stderr,":-( unable to open64(\"%s\",O_RDWR): ", odevice), perror (NULL), exit (FATAL_START(errno)); } device=odevice; goto opened_rw; } if ((mmc_profile&0xFFFF) == 0x12) goto open_rw; /* DVD-RAM */ else goto open_poor_man;}#elif defined(__OpenBSD__) || defined(__NetBSD__)char *setup_fds (char *device){ uid_t uid=getuid(); struct stat sb,sc; /* * We might be entering as euid=root! */ if ((in_fd = open (device,O_RDONLY)) < 0) fprintf (stderr,":-( unable to open(\"%s\",O_RDONLY): ",device), perror (NULL), exit (FATAL_START(errno)); if (fstat (in_fd,&sb) < 0) fprintf (stderr,":-( unable to stat(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (!S_ISCHR(sb.st_mode)) { if (S_ISBLK(sb.st_mode) && !strncmp (device,"/dev/cd",7)) { fprintf (stderr,":-) you most likely want to use /dev/r%s instead!\n", device+5); if (isatty(0) && !dry_run) poll(NULL,0,5000); } setuid(uid); /* drop all privileges */ close (in_fd); /* reopen as mortal */ if ((in_fd = open (device,O_RDONLY)) < 0) fprintf (stderr,":-( unable to reopen(\"%s\",O_RDONLY): ",device), perror (NULL), exit (FATAL_START(errno)); open_rw: if ((out_fd = open (device,O_RDWR)) < 0) fprintf (stderr,":-( unable to open(\"%s\",O_RDWR): ",device), perror (NULL), exit (FATAL_START(errno)); opened_rw: poor_man = 0; close (ioctl_fd); ioctl_handle = INVALID_HANDLE; setuid (uid); /* drop all privileges */ return device; } /* * Still as euid=root! But note that get_mmc_profile makes sure it's * an MMC device, as it terminates the program if the unit doesn't * reply to GET CONFIGURATON. In combination with following switch * this means that if installed set-root-uid, growisofs grants * access to DVD burner(s), but not to any other device. */ ioctl_handle = (void *)(long)open (device,O_RDWR); /* O_RDWR is a must for SCIOCCOMMAND */ if (ioctl_handle == INVALID_HANDLE) { fprintf (stderr,":-( unable to open(\"%s\",O_RDWR): ",device), perror (NULL); if (errno == EBUSY) fprintf (stderr," is its block counterpart mounted?\n"); exit (FATAL_START(errno)); } if (fstat(ioctl_fd,&sc) < 0) fprintf (stderr,":-( unable to stat(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (sb.st_dev!=sc.st_dev || sb.st_ino!=sc.st_ino) fprintf (stderr,":-( %s: race condition detected!\n",device), exit(FATAL_START(EPERM)); mmc_profile = get_mmc_profile (ioctl_handle); switch (mmc_profile&0xFFFF) { case 0x11: /* DVD-R */ case 0x13: /* DVD-RW Restricted Overwrite */ case 0x14: /* DVD-RW Sequential */ case 0x1A: /* DVD+RW */ case 0x1B: /* DVD+R */ case 0x2B: /* DVD+R Double Layer */ open_poor_man: poor_man = 1; out_fd = dup(ioctl_fd); setuid (uid); /* drop all privileges */ return ioctl_device=device; case 0x12: /* DVD-RAM */ if (poor_man>0) goto open_poor_man; out_fd = dup(ioctl_fd); goto opened_rw; default: fprintf (stderr,":-( %s: media is not recognized as " "recordable DVD: %X\n",device,mmc_profile); exit (FATAL_START(EMEDIUMTYPE)); } /* not actually reached */ setuid(uid); goto open_rw;}#elif defined(__FreeBSD__)#include <sys/cdio.h>#include <camlib.h>#include <cam/scsi/scsi_pass.h>#undef ioctl_fd#define ioctl_fd (((struct cam_device *)ioctl_handle)->fd)#define PASS_STDIN_TO_MKISOFSchar *setup_fds (char *device){ uid_t uid=getuid(); struct stat sb,sc; union ccb ccb; char pass[32]; /* periph_name is 16 chars long */ struct cam_device *cam; int once=1; /* * We might be entering as euid=root! */ if ((in_fd = open (device,O_RDONLY)) < 0) fprintf (stderr,":-( unable to open(\"%s\",O_RDONLY): ",device), perror (NULL), exit (FATAL_START(errno)); if (fstat (in_fd,&sb) < 0) fprintf (stderr,":-( unable to stat(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (!S_ISCHR(sb.st_mode)) { setuid(uid); /* drop all privileges */ close (in_fd); /* reopen as mortal */ if ((in_fd = open (device,O_RDONLY)) < 0) fprintf (stderr,":-( unable to reopen(\"%s\",O_RDONLY): ",device), perror (NULL), exit (FATAL_START(errno)); open_rw: if ((out_fd = open (device,O_RDWR)) < 0) fprintf (stderr,":-( unable to open(\"%s\",O_RDWR): ",device), perror (NULL), exit (FATAL_START(errno)); if (fstat(out_fd,&sc) < 0) fprintf (stderr,":-( unable to stat(\"%s\"): ",device), perror (NULL), exit (FATAL_START(errno)); if (sb.st_dev!=sc.st_dev || sb.st_ino!=sc.st_ino) fprintf (stderr,":-( %s: race condition detected!\n",device), exit(FATAL_START(EPERM)); opened_rw: poor_man = 0; if (ioctl_handle && ioctl_handle != INVALID_HANDLE) cam_close_device (ioctl_handle); ioctl_handle = INVALID_HANDLE; setuid (uid); /* drop all privileges */ return device; } /* * Still as euid=root! But note that get_mmc_profile makes sure it's * an MMC device, as it terminates the program if the unit doesn't * reply to GET CONFIGURATON. In combination with following switch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -