static void __init led_init() { struct device *dev; if ((dev = mkdev(0, 0, &ops, "led"))) gpio_init(PIN_STATUS_LED, GPIO_MODE_OUTPUT); }
int virtualfs_custom_stat(struct file *f, struct newstat *buf) { AcquireSRWLockShared(&f->rw_lock); struct virtualfs_custom *file = (struct virtualfs_custom *)f; struct virtualfs_custom_desc *desc = (struct virtualfs_custom_desc *)file->desc; INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(0, 1); buf->st_ino = 0; buf->st_mode = S_IFCHR + 0644; buf->st_nlink = 1; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = desc->device; buf->st_size = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = 0; buf->st_atime = 0; buf->st_atime_nsec = 0; buf->st_mtime = 0; buf->st_mtime_nsec = 0; buf->st_ctime = 0; buf->st_ctime_nsec = 0; ReleaseSRWLockShared(&f->rw_lock); return 0; }
static int winfs_stat(struct file *f, struct newstat *buf) { struct winfs_file *winfile = (struct winfs_file *) f; BY_HANDLE_FILE_INFORMATION info; if (!GetFileInformationByHandle(winfile->handle, &info)) { log_warning("GetFileInformationByHandle() failed.\n"); return -1; /* TODO */ } /* Programs (ld.so) may use st_dev and st_ino to identity files so these must be unique for each file. */ INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(8, 0); // (8, 0): /dev/sda //buf->st_ino = ((uint64_t)info.nFileIndexHigh << 32ULL) + info.nFileIndexLow; /* Hash 64 bit inode to 32 bit to fix legacy applications * We may later add an option for changing this behaviour */ buf->st_ino = info.nFileIndexHigh ^ info.nFileIndexLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) buf->st_mode = 0555; else buf->st_mode = 0755; if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { buf->st_mode |= S_IFDIR; buf->st_size = 0; } else { int r; if ((info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && (r = winfs_read_symlink(winfile->handle, NULL, 0)) > 0) { buf->st_mode |= S_IFLNK; buf->st_size = r; } else { buf->st_mode |= S_IFREG; buf->st_size = ((uint64_t)info.nFileSizeHigh << 32ULL) + info.nFileSizeLow; } } buf->st_nlink = info.nNumberOfLinks; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; buf->st_atime = filetime_to_unix_sec(&info.ftLastAccessTime); buf->st_atime_nsec = filetime_to_unix_nsec(&info.ftLastAccessTime); buf->st_mtime = filetime_to_unix_sec(&info.ftLastWriteTime); buf->st_mtime_nsec = filetime_to_unix_nsec(&info.ftLastWriteTime); buf->st_ctime = filetime_to_unix_sec(&info.ftCreationTime); buf->st_ctime_nsec = filetime_to_unix_nsec(&info.ftCreationTime); return 0; }
static int console_stat(struct file *f, struct newstat *buf) { INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(0, 1); buf->st_ino = 0; buf->st_mode = S_IFCHR + 0644; buf->st_nlink = 1; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = mkdev(5, 1); buf->st_size = 0; buf->st_blksize = 4096; buf->st_blocks = 0; buf->st_atime = 0; buf->st_atime_nsec = 0; buf->st_mtime = 0; buf->st_mtime_nsec = 0; buf->st_ctime = 0; buf->st_ctime_nsec = 0; return 0; }
static int virtualfs_directory_stat(struct file *f, struct newstat *buf) { INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(0, 1); buf->st_ino = 0; buf->st_mode = S_IFDIR + 0644; buf->st_nlink = 1; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = 0; buf->st_size = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = 0; buf->st_atime = 0; buf->st_atime_nsec = 0; buf->st_mtime = 0; buf->st_mtime_nsec = 0; buf->st_ctime = 0; buf->st_ctime_nsec = 0; return 0; }
static void early_mounts(void) { mount("proc", "/proc", "proc", MS_NOATIME, 0); mount("sysfs", "/sys", "sysfs", MS_NOATIME, 0); mount("none", "/sys/fs/cgroup", "cgroup", 0, 0); mount("tmpfs", "/dev", "tmpfs", MS_NOATIME, "mode=0755,size=512K"); mkdir("/dev/shm", 0755); mkdir("/dev/pts", 0755); mount("devpts", "/dev/pts", "devpts", MS_NOATIME, "mode=600"); early_dev(); early_console("/dev/console"); if (mount_zram_on_tmp()) mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, NULL); else mkdev("*", 0600); mkdir("/tmp/run", 0777); mkdir("/tmp/lock", 0777); mkdir("/tmp/state", 0777); }
static int virtualfs_char_stat(struct file *f, struct newstat *buf) { struct virtualfs_char *file = (struct virtualfs_char *)f; INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(0, 1); buf->st_ino = 0; buf->st_mode = S_IFCHR + 0644; buf->st_nlink = 1; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = file->desc->device; buf->st_size = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = 0; buf->st_atime = 0; buf->st_atime_nsec = 0; buf->st_mtime = 0; buf->st_mtime_nsec = 0; buf->st_ctime = 0; buf->st_ctime_nsec = 0; return 0; }
static void early_dev(void) { mkdev("*", 0600); mknod("/dev/null", 0666, makedev(1, 3)); }
int main(int argc, char **argv) { char *prog, *optstr, *usagestr; int c, background, unit, active; char base[PATH_MAX], path[PATH_MAX]; unsigned int mode, hdr, xrun, rate, join, mmc, vol; unsigned int hold, autovol, bufsz, round; const char *str; struct aparams ppar, rpar; struct dev *d, *dnext; struct listen *l; struct wav *w; /* * global options defaults */ hdr = HDR_AUTO; xrun = XRUN_IGNORE; vol = MIDI_MAXCTL; join = 1; mmc = 0; hold = 0; autovol = 1; bufsz = 0; round = 0; unit = 0; background = 0; aparams_init(&ppar, 0, 1, DEFAULT_RATE); aparams_init(&rpar, 0, 1, DEFAULT_RATE); mode = MODE_MIDIMASK | MODE_PLAY | MODE_REC; #ifdef DEBUG atexit(dbg_flush); #endif setsig(); filelist_init(); prog = strrchr(argv[0], '/'); if (prog == NULL) prog = argv[0]; else prog++; if (strcmp(prog, PROG_AUCAT) == 0) { optstr = "a:b:c:C:de:f:h:i:j:lL:m:Mno:q:r:s:t:U:v:w:x:z:"; usagestr = aucat_usage; } else if (strcmp(prog, PROG_SNDIOD) == 0) { optstr = "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:"; usagestr = sndiod_usage; background = 1; hold = 0; } else { fprintf(stderr, "%s: can't determine program to run\n", prog); return 1; } while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case 'd': #ifdef DEBUG if (debug_level < 4) debug_level++; #endif background = 0; break; case 'U': if (listen_list) errx(1, "-U must come before -L"); unit = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: unit number is %s", optarg, str); break; case 'L': listen_new_tcp(optarg, AUCAT_PORT + unit); break; case 'm': mode = opt_mode(); break; case 'h': hdr = opt_hdr(); break; case 'x': xrun = opt_xrun(); break; case 'j': join = opt_onoff(); break; case 't': mmc = opt_mmc(); break; case 'c': opt_ch(&ppar); break; case 'C': opt_ch(&rpar); break; case 'e': opt_enc(&ppar); aparams_copyenc(&rpar, &ppar); break; case 'r': rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str); if (str) errx(1, "%s: rate is %s", optarg, str); ppar.rate = rpar.rate = rate; break; case 'v': vol = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: volume is %s", optarg, str); break; case 'i': d = mkdev(NULL, 0, bufsz, round, 1, autovol); w = wav_new_in(&wav_ops, d, mode & (MODE_PLAY | MODE_MIDIOUT), optarg, hdr, &ppar, xrun, vol, mmc, join); if (w == NULL) errx(1, "%s: couldn't create stream", optarg); dev_adjpar(d, w->mode, NULL, &w->hpar); break; case 'o': d = mkdev(NULL, 0, bufsz, round, 1, autovol); w = wav_new_out(&wav_ops, d, mode & (MODE_RECMASK | MODE_MIDIIN), optarg, hdr, &rpar, xrun, mmc, join); if (w == NULL) errx(1, "%s: couldn't create stream", optarg); dev_adjpar(d, w->mode, &w->hpar, NULL); break; case 's': if ((d = dev_list) == NULL) { d = mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol); } mkopt(optarg, d, &rpar, &ppar, mode, vol, mmc, join); /* XXX: set device rate, if never set */ break; case 'q': d = mkdev(NULL, mode, bufsz, round, 1, autovol); if (!devctl_add(d, optarg, MODE_MIDIMASK)) errx(1, "%s: can't open port", optarg); d->reqmode |= MODE_MIDIMASK; break; case 'a': hold = opt_onoff(); break; case 'w': autovol = opt_onoff(); break; case 'b': bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str); if (str) errx(1, "%s: buffer size is %s", optarg, str); break; case 'z': round = strtonum(optarg, 1, SHRT_MAX, &str); if (str) errx(1, "%s: block size is %s", optarg, str); break; case 'f': mkdev(optarg, 0, bufsz, round, hold, autovol); break; case 'n': mkdev("loopback", MODE_LOOP, bufsz, round, 1, autovol); break; case 'M': mkdev("midithru", MODE_THRU, 0, 0, hold, 0); break; case 'l': background = 1; break; default: fputs(usagestr, stderr); exit(1); } } argc -= optind; argv += optind; if (argc > 0) { fputs(usagestr, stderr); exit(1); } if (wav_list) { if (opt_list || listen_list) errx(1, "-io not allowed in server mode"); if ((d = dev_list) && d->next) errx(1, "only one device allowed in non-server mode"); if ((d->reqmode & MODE_THRU) && d->ctl_list == NULL) { if (!devctl_add(d, "default", MODE_MIDIMASK)) errx(1, "%s: can't open port", optarg); d->reqmode |= MODE_MIDIMASK; } } else { if (dev_list == NULL) mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol); for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join); } } if (opt_list) { getbasepath(base, sizeof(base)); snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); listen_new_un(path); if (geteuid() == 0) privdrop(); } for (w = wav_list; w != NULL; w = w->next) { if (!wav_init(w)) exit(1); } for (d = dev_list; d != NULL; d = d->next) { if (!dev_init(d)) exit(1); if (d->autostart && (d->mode & MODE_AUDIOMASK)) dev_mmcstart(d); } for (l = listen_list; l != NULL; l = l->next) { if (!listen_init(l)) exit(1); } if (background) { #ifdef DEBUG debug_level = 0; dbg_flush(); #endif if (daemon(0, 0) < 0) err(1, "daemon"); } /* * Loop, start audio. */ for (;;) { if (quit_flag) break; active = 0; for (d = dev_list; d != NULL; d = dnext) { dnext = d->next; if (!dev_run(d)) goto fatal; if (d->refcnt > 0) active = 1; } if (dev_list == NULL) break; if (!opt_list && !active) break; if (!file_poll()) break; } fatal: while (listen_list != NULL) file_close(&listen_list->file); /* * give a chance to drain */ for (d = dev_list; d != NULL; d = d->next) dev_drain(d); while (file_poll()) ; /* nothing */ while (dev_list) dev_del(dev_list); filelist_done(); if (opt_list) { if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM) warn("rmdir(\"%s\")", base); } unsetsig(); return 0; }
int main(int argc, char **argv) { int c, background, unit; int pmin, pmax, rmin, rmax; char base[PATH_MAX], path[PATH_MAX]; unsigned int mode, dup, mmc, vol; unsigned int hold, autovol, bufsz, round, rate; const char *str; struct aparams par; struct dev *d; struct port *p; struct listen *l; atexit(log_flush); /* * global options defaults */ vol = 118; dup = 1; mmc = 0; hold = 0; autovol = 1; bufsz = 0; round = 0; rate = DEFAULT_RATE; unit = 0; background = 1; pmin = 0; pmax = 1; rmin = 0; rmax = 1; aparams_init(&par); mode = MODE_PLAY | MODE_REC; setsig(); filelist_init(); while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:")) != -1) { switch (c) { case 'd': log_level++; background = 0; break; case 'U': if (listen_list) errx(1, "-U must come before -L"); unit = strtonum(optarg, 0, 15, &str); if (str) errx(1, "%s: unit number is %s", optarg, str); break; case 'L': listen_new_tcp(optarg, AUCAT_PORT + unit); break; case 'm': mode = opt_mode(); break; case 'j': dup = opt_onoff(); break; case 't': mmc = opt_mmc(); break; case 'c': opt_ch(&pmin, &pmax); break; case 'C': opt_ch(&rmin, &rmax); break; case 'e': opt_enc(&par); break; case 'r': rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str); if (str) errx(1, "%s: rate is %s", optarg, str); break; case 'v': vol = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: volume is %s", optarg, str); break; case 's': if ((d = dev_list) == NULL) { d = mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); } mkopt(optarg, d, pmin, pmax, rmin, rmax, mode, vol, mmc, dup); break; case 'q': p = port_new(optarg, MODE_MIDIMASK, hold); if (!p) errx(1, "%s: can't open port", optarg); break; case 'a': hold = opt_onoff(); break; case 'w': autovol = opt_onoff(); break; case 'b': bufsz = strtonum(optarg, 1, RATE_MAX, &str); if (str) errx(1, "%s: buffer size is %s", optarg, str); break; case 'z': round = strtonum(optarg, 1, SHRT_MAX, &str); if (str) errx(1, "%s: block size is %s", optarg, str); break; case 'f': mkdev(optarg, &par, 0, bufsz, round, rate, hold, autovol); break; case 'M': /* XXX: for compatibility with aucat, remove this */ break; default: fputs(usagestr, stderr); return 1; } } argc -= optind; argv += optind; if (argc > 0) { fputs(usagestr, stderr); return 1; } if (dev_list == NULL) mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; mkopt("default", d, pmin, pmax, rmin, rmax, mode, vol, mmc, dup); } getbasepath(base, sizeof(base)); snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); listen_new_un(path); if (geteuid() == 0) privdrop(); midi_init(); for (p = port_list; p != NULL; p = p->next) { if (!port_init(p)) return 1; } for (d = dev_list; d != NULL; d = d->next) { if (!dev_init(d)) return 1; } for (l = listen_list; l != NULL; l = l->next) { if (!listen_init(l)) return 1; } if (background) { log_flush(); log_level = 0; if (daemon(0, 0) < 0) err(1, "daemon"); } /* * Loop, start audio. */ for (;;) { if (quit_flag) break; if (!file_poll()) break; } while (listen_list != NULL) listen_close(listen_list); while (sock_list != NULL) sock_close(sock_list); while (opt_list != NULL) opt_del(opt_list); for (d = dev_list; d != NULL; d = d->next) dev_done(d); for (p = port_list; p != NULL; p = p->next) port_done(p); midi_done(); while (file_poll()) ; /* nothing */ while (dev_list) dev_del(dev_list); while (port_list) port_del(port_list); filelist_done(); rmdir(base); unsetsig(); return 0; }
} ReleaseSRWLockExclusive(&f->rw_lock); return r; } static const struct file_ops dsp_ops = { .close = dsp_close, .read = dsp_read, .write = dsp_write, .stat = virtualfs_custom_stat, .ioctl = dsp_ioctl, }; static struct file *dsp_alloc(); struct virtualfs_custom_desc dsp_desc = VIRTUALFS_CUSTOM(mkdev(14, 3), dsp_alloc); static struct file *dsp_alloc() { struct dsp_file *f = (struct dsp_file *)kmalloc(sizeof(struct dsp_file)); file_init(&f->custom_file.base_file, &dsp_ops, O_LARGEFILE | O_RDWR); virtualfs_init_custom(f, &dsp_desc); f->waveout = NULL; SECURITY_ATTRIBUTES attr; attr.nLength = sizeof(SECURITY_ATTRIBUTES); attr.bInheritHandle = FALSE; attr.lpSecurityDescriptor = NULL; for (int i = 0; i < DSP_BUFFER_COUNT; i++) f->buffer[i].event = CreateEventW(&attr, FALSE, TRUE, NULL); dsp_reset(f); return (struct file *)f;
static int winfs_stat(struct file *f, struct newstat *buf) { AcquireSRWLockShared(&f->rw_lock); struct winfs_file *winfile = (struct winfs_file *) f; BY_HANDLE_FILE_INFORMATION info; GetFileInformationByHandle(winfile->handle, &info); /* Programs (ld.so) may use st_dev and st_ino to identity files so these must be unique for each file. */ INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(8, 0); // (8, 0): /dev/sda //buf->st_ino = ((uint64_t)info.nFileIndexHigh << 32ULL) + info.nFileIndexLow; /* Hash 64 bit inode to 32 bit to fix legacy applications * We may later add an option for changing this behaviour */ buf->st_ino = info.nFileIndexHigh ^ info.nFileIndexLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) buf->st_mode = 0555; else buf->st_mode = 0755; if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { buf->st_mode |= S_IFDIR; buf->st_size = 0; } else { buf->st_mode |= S_IFREG; buf->st_size = ((uint64_t)info.nFileSizeHigh << 32ULL) + info.nFileSizeLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) { WaitForSingleObject(winfile->fp_mutex, INFINITE); /* Save current file pointer */ LARGE_INTEGER distanceToMove, currentFilePointer; distanceToMove.QuadPart = 0; SetFilePointerEx(winfile->handle, distanceToMove, ¤tFilePointer, FILE_CURRENT); int type = winfs_get_special_file_type(winfile->handle); if (type > 0) { if (type == SPECIAL_FILE_SYMLINK) { buf->st_mode |= S_IFLNK; buf->st_size -= WINFS_SYMLINK_HEADER_LEN; } else if (type == SPECIAL_FILE_SOCKET) { buf->st_mode |= S_IFSOCK; buf->st_size = 0; } } /* Restore current file pointer */ SetFilePointerEx(winfile->handle, currentFilePointer, ¤tFilePointer, FILE_BEGIN); ReleaseMutex(winfile->fp_mutex); } } buf->st_nlink = info.nNumberOfLinks; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; buf->st_atime = filetime_to_unix_sec(&info.ftLastAccessTime); buf->st_atime_nsec = filetime_to_unix_nsec(&info.ftLastAccessTime); buf->st_mtime = filetime_to_unix_sec(&info.ftLastWriteTime); buf->st_mtime_nsec = filetime_to_unix_nsec(&info.ftLastWriteTime); buf->st_ctime = filetime_to_unix_sec(&info.ftCreationTime); buf->st_ctime_nsec = filetime_to_unix_nsec(&info.ftCreationTime); ReleaseSRWLockShared(&f->rw_lock); return 0; }
#include <log.h> #define SystemFunction036 NTAPI SystemFunction036 #include <NTSecAPI.h> #undef SystemFunction036 DEFINE_SYSCALL(getrandom, void *, buf, size_t, buflen, unsigned int, flags) { log_info("getrandom(%p, %d, %x)", buf, buflen, flags); if (!mm_check_write(buf, buflen)) return -L_EFAULT; if (!RtlGenRandom(buf, buflen)) return 0; return buflen; } static size_t random_read(int tag, void *buf, size_t count) { if (!RtlGenRandom(buf, count)) return 0; return count; } static size_t random_write(int tag, const void *buf, size_t count) { return count; } struct virtualfs_char_desc random_desc = VIRTUALFS_CHAR(mkdev(1, 8), random_read, random_write); struct virtualfs_char_desc urandom_desc = VIRTUALFS_CHAR(mkdev(1, 9), random_read, random_write);
} default: log_error("console: unknown ioctl command: %x\n", cmd); r = -EINVAL; break; } console_unlock(); return r; } static const struct file_ops console_ops = { .get_poll_status = console_get_poll_status, .get_poll_handle = console_get_poll_handle, .close = console_close, .read = console_read, .write = console_write, .stat = virtualfs_custom_stat, .ioctl = console_ioctl, }; struct virtualfs_custom_desc console_desc = VIRTUALFS_CUSTOM(mkdev(5, 1), console_alloc); struct file *console_alloc() { struct console_file *f = (struct console_file *)kmalloc(sizeof(struct console_file)); file_init(&f->custom_file.base_file, &console_ops, O_LARGEFILE | O_RDWR); virtualfs_init_custom(f, &console_desc); return (struct file *)f; }