示例#1
0
文件: test.c 项目: NTmatter/Netatalk
int main(int argc, char **argv)
{
    int reti;
    uint16_t vid;
    struct vol *vol;
    struct dir *retdir;
    struct path *path;

    /* initialize */
    printf("Initializing\n============\n");
    TEST(setuplog("default:note","/dev/tty"));

    TEST( afp_options_parse_cmdline(&obj, 3, &args[0]) );

    TEST_int( afp_config_parse(&obj, NULL), 0);
    TEST_int( configinit(&obj), 0);
    TEST( cnid_init() );
    TEST( load_volumes(&obj, NULL) );
    TEST_int( dircache_init(8192), 0);
    obj.afp_version = 32;

    printf("\n");

    /* now run tests */
    printf("Running tests\n=============\n");

    TEST_expr(vid = openvol(&obj, "test"), vid != 0);
    TEST_expr(vol = getvolbyvid(vid), vol != NULL);

    /* test directory.c stuff */
    TEST_expr(retdir = dirlookup(vol, DIRDID_ROOT_PARENT), retdir != NULL);
    TEST_expr(retdir = dirlookup(vol, DIRDID_ROOT), retdir != NULL);
    TEST_expr(path = cname(vol, retdir, cnamewrap("Network Trash Folder")), path != NULL);

    TEST_expr(retdir = dirlookup(vol, DIRDID_ROOT), retdir != NULL);
    TEST_int(getfiledirparms(&obj, vid, DIRDID_ROOT_PARENT, "test"), 0);
    TEST_int(getfiledirparms(&obj, vid, DIRDID_ROOT, ""), 0);

    TEST_expr(reti = createdir(&obj, vid, DIRDID_ROOT, "dir1"),
              reti == 0 || reti == AFPERR_EXIST);

    TEST_int(getfiledirparms(&obj, vid, DIRDID_ROOT, "dir1"), 0);
/*
  FIXME: this doesn't work although it should. "//" get translated to \000 \000 at means ".."
  ie this should getfiledirparms for DIRDID_ROOT_PARENT -- at least afair!
    TEST_int(getfiledirparms(&configs->obj, vid, DIRDID_ROOT, "//"), 0);
*/
    TEST_int(createfile(&obj, vid, DIRDID_ROOT, "dir1/file1"), 0);
    TEST_int(delete(&obj, vid, DIRDID_ROOT, "dir1/file1"), 0);
    TEST_int(delete(&obj, vid, DIRDID_ROOT, "dir1"), 0);

    TEST_int(createfile(&obj, vid, DIRDID_ROOT, "file1"), 0);
    TEST_int(getfiledirparms(&obj, vid, DIRDID_ROOT, "file1"), 0);
    TEST_int(delete(&obj, vid, DIRDID_ROOT, "file1"), 0);


    /* test enumerate.c stuff */
    TEST_int(enumerate(&obj, vid, DIRDID_ROOT), 0);
}
示例#2
0
文件: ad.c 项目: Netatalk/Netatalk
int main(int argc, char **argv)
{
    AFPObj obj = { 0 };

    if (argc < 2) {
        usage_main();
        return 1;
    }

    if (afp_config_parse(&obj, "ad") != 0)
        return 1;

    setuplog("default:note", "/dev/tty");

    if (load_volumes(&obj, LV_DEFAULT) != 0)
        return 1;

    if (STRCMP(argv[1], ==, "ls"))
        return ad_ls(argc - 1, argv + 1, &obj);
    else if (STRCMP(argv[1], ==, "cp"))
示例#3
0
int main(int argc, char **argv)
{
    int c, lockfd, ret = -1;
    int dump=0, scan=0, rebuild=0, prep_upgrade=0, rebuildindexes=0, dumpindexes=0, force=0;
    dbd_flags_t flags = 0;
    char *volpath;
    int cdir;
    AFPObj obj = { 0 };
    struct vol *vol;

    if (geteuid() != 0) {
        usage();
        exit(EXIT_FAILURE);
    }
    /* Inhereting perms in ad_mkdir etc requires this */
    ad_setfuid(0);

    while ((c = getopt(argc, argv, ":cCdefFinrstuvx")) != -1) {
        switch(c) {
        case 'c':
            flags |= DBD_FLAGS_CLEANUP;
            break;
        case 'C':
            flags |= DBD_FLAGS_V2TOEA;
            break;
        case 'd':
            dump = 1;
            break;
        case 'i':
            dumpindexes = 1;
            break;
        case 's':
            scan = 1;
            flags |= DBD_FLAGS_SCAN;
            break;
        case 'n':
            nocniddb = 1; /* FIXME: this could/should be a flag too for consistency */
            break;
        case 'r':
            rebuild = 1;
            break;
        case 't':
            flags |= DBD_FLAGS_STATS;
            break;
        case 'u':
            prep_upgrade = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'e':
            exclusive = 1;
            flags |= DBD_FLAGS_EXCL;
            break;
        case 'x':
            rebuildindexes = 1;
            break;
        case 'f':
            force = 1;
            exclusive = 1;
            flags |= DBD_FLAGS_FORCE | DBD_FLAGS_EXCL;
            break;
        case 'F':
            obj.cmdlineconfigfile = strdup(optarg);
            break;
        case ':':
        case '?':
            usage();
            exit(EXIT_FAILURE);
            break;
        }
    }

    if ((dump + scan + rebuild + prep_upgrade) != 1) {
        usage();
        exit(EXIT_FAILURE);
    }

    if ( (optind + 1) != argc ) {
        usage();
        exit(EXIT_FAILURE);
    }
    volpath = argv[optind];

    setvbuf(stdout, (char *) NULL, _IONBF, 0);

    /* Remember cwd */
    if ((cdir = open(".", O_RDONLY)) < 0) {
        dbd_log( LOGSTD, "Can't open dir: %s", strerror(errno));
        exit(EXIT_FAILURE);
    }
        
    /* Setup signal handling */
    set_signal();

    /* Setup logging. Should be portable among *NIXes */
    if (!verbose)
        setuplog("default:info", "/dev/tty");
    else
        setuplog("default:debug", "/dev/tty");

    /* Load config */
    if (afp_config_parse(&obj, "dbd") != 0) {
        dbd_log( LOGSTD, "Couldn't load afp.conf");
        exit(EXIT_FAILURE);
    }

    if (load_volumes(&obj, NULL) != 0) {
        dbd_log( LOGSTD, "Couldn't load volumes");
        exit(EXIT_FAILURE);
    }

    if ((vol = getvolbypath(&obj, volpath)) == NULL) {
        dbd_log( LOGSTD, "Couldn't find volume for '%s'", volpath);
        exit(EXIT_FAILURE);
    }

    if (load_charset(vol) != 0) {
        dbd_log( LOGSTD, "Couldn't load charsets for '%s'", volpath);
        exit(EXIT_FAILURE);
    }

    pack_setvol(vol);

    if (vol->v_adouble == AD_VERSION_EA)
        dbd_log( LOGDEBUG, "adouble:ea volume");
    else if (vol->v_adouble == AD_VERSION2)
        dbd_log( LOGDEBUG, "adouble:v2 volume");
    else {
        dbd_log( LOGSTD, "unknown adouble volume");
        exit(EXIT_FAILURE);
    }

    /* -C v2 to ea conversion only on adouble:ea volumes */
    if ((flags & DBD_FLAGS_V2TOEA) && (vol->v_adouble!= AD_VERSION_EA)) {
        dbd_log( LOGSTD, "Can't run adouble:v2 to adouble:ea conversion because not an adouble:ea volume");
        exit(EXIT_FAILURE);
    }

    /* Sanity checks to ensure we can touch this volume */
    if (vol->v_vfs_ea != AFPVOL_EA_AD && vol->v_vfs_ea != AFPVOL_EA_SYS) {
        dbd_log( LOGSTD, "Unknown Extended Attributes option: %u", vol->v_vfs_ea);
        exit(EXIT_FAILURE);        
    }

    /* Enuser dbpath is there, create if necessary */
    struct stat st;
    if (stat(vol->v_dbpath, &st) != 0) {
        if (errno != ENOENT) {
            dbd_log( LOGSTD, "Can't stat dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
            exit(EXIT_FAILURE);        
        }
        if ((mkdir(vol->v_dbpath, 0755)) != 0) {
            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
            exit(EXIT_FAILURE);
        }        
    }

    /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
    if ( (strlen(vol->v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
        dbd_log( LOGSTD, "Volume pathname too long");
        exit(EXIT_FAILURE);        
    }
    strncpy(dbpath, vol->v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
    strcat(dbpath, "/.AppleDB");

    /* Check or create dbpath */
    int dbdirfd = open(dbpath, O_RDONLY);
    if (dbdirfd == -1 && errno == ENOENT) {
        if (errno == ENOENT) {
            if ((mkdir(dbpath, 0755)) != 0) {
                dbd_log( LOGSTD, "Can't create .AppleDB for \"%s\": %s", dbpath, strerror(errno));
                exit(EXIT_FAILURE);
            }
        } else {
            dbd_log( LOGSTD, "Somethings wrong with .AppleDB for \"%s\", giving up: %s", dbpath, strerror(errno));
            exit(EXIT_FAILURE);
        }
    } else {
        close(dbdirfd);
    }

    /* Get db lock */
    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
        goto exit_noenv;
    if (db_locked != LOCK_EXCL) {
        /* Couldn't get exclusive lock, try shared lock if -e wasn't requested */
        if (exclusive) {
            dbd_log(LOGSTD, "Database is in use and exlusive was requested");
            goto exit_noenv;
        }
        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD)
            goto exit_noenv;
    }

    /* Check if -f is requested and wipe db if yes */
    if ((flags & DBD_FLAGS_FORCE) && rebuild) {
        char cmd[8 + MAXPATHLEN];
        if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
            goto exit_noenv;

        snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
        dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
        system(cmd);
        if ((mkdir(dbpath, 0755)) != 0) {
            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", dbpath, strerror(errno));
            exit(EXIT_FAILURE);
        }
        dbd_log( LOGDEBUG, "Removed old database.");
        if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
            goto exit_noenv;
    }

    /* 
       Lets start with the BerkeleyDB stuff
    */
    if ( ! nocniddb) {
        if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
            goto exit_noenv;
        
        if (dbif_env_open(dbd,
                          &db_param,
                          (db_locked == LOCK_EXCL) ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
            dbd_log( LOGSTD, "error opening database!");
            goto exit_noenv;
        }

        if (db_locked == LOCK_EXCL)
            dbd_log( LOGDEBUG, "Finished recovery.");

        if (dbif_open(dbd, NULL, rebuildindexes) < 0) {
            dbif_close(dbd);
            goto exit_failure;
        }

        /* Prepare upgrade ? We're done */
        if (prep_upgrade) {
            (void)dbif_txn_close(dbd, 1);
            goto cleanup;
        }
    }

    /* Downgrade db lock if not running exclusive */
    if (!exclusive && (db_locked == LOCK_EXCL)) {
        if (get_lock(LOCK_UNLOCK, NULL) != 0)
            goto exit_failure;
        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
            goto exit_failure;
    }

    /* Now execute given command scan|rebuild|dump */
    if (dump && ! nocniddb) {
        if (dbif_dump(dbd, dumpindexes) < 0) {
            dbd_log( LOGSTD, "Error dumping database");
        }
    } else if ((rebuild && ! nocniddb) || scan) {
        if (cmd_dbd_scanvol(dbd, vol, flags) < 0) {
            dbd_log( LOGSTD, "Error repairing database.");
        }
    }

cleanup:
    /* Cleanup */
    dbd_log(LOGDEBUG, "Closing db");
    if (! nocniddb) {
        if (dbif_close(dbd) < 0) {
            dbd_log( LOGSTD, "Error closing database");
            goto exit_failure;
        }
    }

exit_success:
    ret = 0;

exit_failure:
    if (dbif_env_remove(dbpath) < 0) {
        dbd_log( LOGSTD, "Error removing BerkeleyDB database environment");
        ret++;
    }
    get_lock(0, NULL);

exit_noenv:    
    if ((fchdir(cdir)) < 0)
        dbd_log(LOGSTD, "fchdir: %s", strerror(errno));

    if (ret == 0)
        exit(EXIT_SUCCESS);
    else
        exit(EXIT_FAILURE);
}
示例#4
0
文件: main.c 项目: NTmatter/Netatalk
int main(int ac, char **av)
{
    fd_set              rfds;
    void                *ipc;
    struct sigaction	sv;
    sigset_t            sigs;
    int                 ret;

    /* Parse argv args and initialize default options */
    afp_options_parse_cmdline(&obj, ac, av);

    if (!(obj.cmdlineflags & OPTION_DEBUG) && (daemonize(0, 0) != 0))
        exit(EXITERR_SYS);

    /* Log SIGBUS/SIGSEGV SBT */
    fault_setup(NULL);

    if (afp_config_parse(&obj, "afpd") != 0)
        afp_exit(EXITERR_CONF);

    /* Save the user's current umask */
    obj.options.save_mask = umask(obj.options.umask);

    /* install child handler for asp and dsi. we do this before afp_goaway
     * as afp_goaway references stuff from here. 
     * XXX: this should really be setup after the initial connections. */
    if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) {
        LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }
    
    sigemptyset(&sigs);
    pthread_sigmask(SIG_SETMASK, &sigs, NULL);

    memset(&sv, 0, sizeof(sv));    
    /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs,
       even if the file is open with O_LARGEFILE ! */
#ifdef SIGXFSZ
    sv.sa_handler = SIG_IGN;
    sigemptyset( &sv.sa_mask );
    if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }
#endif
    
    sv.sa_handler = afp_goaway; /* handler for all sigs */

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGQUIT);    
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGTERM);
    sv.sa_flags = SA_RESTART;
    if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    /* afp.conf:  not in config file: lockfile, configfile
     *            preference: command-line provides defaults.
     *                        config file over-writes defaults.
     *
     * we also need to make sure that killing afpd during startup
     * won't leave any lingering registered names around.
     */

    sigemptyset(&sigs);
    sigaddset(&sigs, SIGALRM);
    sigaddset(&sigs, SIGHUP);
    sigaddset(&sigs, SIGUSR1);
#if 0
    /* don't block SIGTERM */
    sigaddset(&sigs, SIGTERM);
#endif
    sigaddset(&sigs, SIGCHLD);

    pthread_sigmask(SIG_BLOCK, &sigs, NULL);
    if (configinit(&obj) != 0) {
        LOG(log_error, logtype_afpd, "main: no servers configured");
        afp_exit(EXITERR_CONF);
    }
    pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);

    /* Initialize */
    cnid_init();
    
    /* watch atp, dsi sockets and ipc parent/child file descriptor. */

    if (obj.options.flags & OPTION_KEEPSESSIONS) {
        LOG(log_note, logtype_afpd, "Activating continous service");
        disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
    }

    fd_set_listening_sockets(&obj);

    /* set limits */
    (void)setlimits();

    afp_child_t *child;
    int recon_ipc_fd;
    pid_t pid;
    int saveerrno;

    /* wait for an appleshare connection. parent remains in the loop
     * while the children get handled by afp_over_{asp,dsi}.  this is
     * currently vulnerable to a denial-of-service attack if a
     * connection is made without an actual login attempt being made
     * afterwards. establishing timeouts for logins is a possible 
     * solution. */
    while (1) {
        LOG(log_maxdebug, logtype_afpd, "main: polling %i fds", fdset_used);
        pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
        ret = poll(fdset, fdset_used, -1);
        pthread_sigmask(SIG_BLOCK, &sigs, NULL);
        saveerrno = errno;

        if (gotsigchld) {
            gotsigchld = 0;
            child_handler();
            continue;
        }

        if (reloadconfig) {
            nologin++;
            auth_unload();
            fd_reset_listening_sockets(&obj);

            LOG(log_info, logtype_afpd, "re-reading configuration file");

            configfree(&obj, NULL);
            if (configinit(&obj) != 0) {
                LOG(log_error, logtype_afpd, "config re-read: no servers configured");
                afp_exit(EXITERR_CONF);
            }

            fd_set_listening_sockets(&obj);

            nologin = 0;
            reloadconfig = 0;
            errno = saveerrno;
            continue;
        }

        if (ret == 0)
            continue;
        
        if (ret < 0) {
            if (errno == EINTR)
                continue;
            LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno));
            break;
        }

        for (int i = 0; i < fdset_used; i++) {
            if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) {
                switch (polldata[i].fdtype) {

                case LISTEN_FD:
                    if (child = dsi_start(&obj, (DSI *)polldata[i].data, server_children)) {
                        /* Add IPC fd to select fd set */
                        fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
                                     &fdset,
                                     &polldata,
                                     &fdset_used,
                                     &fdset_size,
                                     child->ipc_fd,
                                     IPC_FD,
                                     child);
                    }
                    break;

                case IPC_FD:
                    child = (afp_child_t *)polldata[i].data;
                    LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);

                    if (ipc_server_read(server_children, child->ipc_fd) != 0) {
                        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd);
                        close(child->ipc_fd);
                        child->ipc_fd = -1;
                        if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
                            LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
                            server_child_remove(server_children, CHILD_DSIFORK, child->pid);
                        }
                    }
                    break;

                case DISASOCIATED_IPC_FD:
                    LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
                    if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
                        LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
                        break;
                    }
                    if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
                        LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
                        close(recon_ipc_fd);
                        break;
                    }
                    LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid);

                    if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) {
                        LOG(log_error, logtype_afpd, "main: server_child_add");
                        close(recon_ipc_fd);
                        break;
                    }
                    child->disasociated = 1;
                    fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
                                 &fdset,
                                 &polldata,
                                 &fdset_used,
                                 &fdset_size,
                                 recon_ipc_fd,
                                 IPC_FD,
                                 child);
                    break;

                default:
                    LOG(log_debug, logtype_afpd, "main: IPC request for unknown type");
                    break;
                } /* switch */
            }  /* if */
        } /* for (i)*/
    } /* while (1) */

    return 0;
}